代码编织梦想

1 拾遗增补

1.1 线程状态

名称

条件

NEW

至今尚未启动的线程

RUNNABLE

正在Java虚拟机中执行的线程

BLOCKED

受阻塞并等待某个监视器锁的线程

WAITING

无限期地等待另一个线程来执行某一特定操作

TIMED WAITING

等待另一个线程来执行,取决于指定等待时间的操作的线程

TERMINATED

已退出的线程

表 Java线程不同状态说明

1.2 线程组

为了方便对某些具有相同功能的线程进行管理,把线程归属到某一个线程组。

图 ThreadGroup的方法

ThreadGroup的interrupt()方法可以批量停止组内的线程。

1.3 线程与线程组的异常处理

1.3.1 线程异常处理

public class ThreadExceptionDeal {

    static class MyThread extends Thread {

        private String numStr;

        MyThread(String numStr) {
            this.numStr = numStr;
        }

        @Override
        public void run() {
            Integer integer = Integer.valueOf(numStr);
            System.out.println(Thread.currentThread().getName() + "执行完成,结果是:" + integer);
        }
    }

    public static void main(String[] args) {
        //设置线程默认的异常处理
        MyThread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("这是线程默认的异常处理:" + t.getName());
                e.printStackTrace();
            }
        });
        MyThread thread0 = new MyThread("21"); //正常
        MyThread thread1 = new MyThread("21a"); //异常
        MyThread thread2 = new MyThread("ab2"); //异常
        thread2.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("这是thread2定制的异常处理");
                e.printStackTrace();
            }
        });

        thread0.start();
        thread1.start();
        thread2.start();
    }

}
/*
运行结果
java.lang.NumberFormatException: For input string: "21a"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:580)
	at java.lang.Integer.valueOf(Integer.java:766)
	at com.huangmingfu.day6.article.ThreadExceptionDeal$MyThread.run(ThreadExceptionDeal.java:15)
java.lang.NumberFormatException: For input string: "ab2"
	at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
	at java.lang.Integer.parseInt(Integer.java:580)
	at java.lang.Integer.valueOf(Integer.java:766)
	at com.huangmingfu.day6.article.ThreadExceptionDeal$MyThread.run(ThreadExceptionDeal.java:15)
这是线程默认的异常处理:Thread-1
这是thread2定制的异常处理
Thread-0执行完成,结果是:21

Process finished with exit code 0
 */

线程用静态方法设置了默认的异常处理器,也可有用实例方法定制异常处理器。 执行逻辑是,如果设置了定制的,则只执行定制异常处理器,否则执行默认的异常处理器。

1.3.2 线程组异常处理

public class ThreadGroupExceptionDeal {

    static class MyThreadGroup extends ThreadGroup {
        public MyThreadGroup(String name) {
            super(name);
        }

        //重写uncaughtException方法来处理异常
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println("线程组内设置的异常处理");
            e.printStackTrace();
        }
    }

    static class MyThread extends Thread {
        private Integer num;

        public MyThread(Integer num,ThreadGroup threadGroup,String name) {
            super(threadGroup,name);
            this.num = num;
        }

        @Override
        public void run() {
            System.out.println( Thread.currentThread().getName() + "执行成功,结果是" + 2 / num);
        }
    }

    public static void main(String[] args) {
        MyThreadGroup myThreadGroup = new MyThreadGroup("我的线程组");
        MyThread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("这是myThread默认的异常处理");
                e.printStackTrace();
            }
        });
        MyThread myThread1 = new MyThread(0,myThreadGroup,"myThread1");
        myThread1.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("thread1定制的异常处理");
                e.printStackTrace();
            }
        });
        MyThread myThread2 = new MyThread(0,myThreadGroup,"myThread2");
        MyThread myThread3 = new MyThread(3,myThreadGroup,"myThread3");

        myThread1.start();
        myThread2.start();
        myThread3.start();
    }

}
/*
运行结果:
java.lang.ArithmeticException: / by zero
	at com.huangmingfu.day6.article.ThreadGroupExceptionDeal$MyThread.run(ThreadGroupExceptionDeal.java:28)
java.lang.ArithmeticException: / by zero
	at com.huangmingfu.day6.article.ThreadGroupExceptionDeal$MyThread.run(ThreadGroupExceptionDeal.java:28)
线程组内设置的异常处理
myThread3执行成功,结果是0
thread1定制的异常处理

Process finished with exit code 0
 */

 

图 ThreadGroup实现了UncaughtExceptionHandler接口

异常处理优先级为:线程定制异常处理 > 线程组重现方法异常处理 > 线程默认异常处理。

2 并发集合框架

2.1 非阻塞队列

队列里面没有数据时,返回异常或null,线程安全。

非线程安全队列

非阻塞队列

功能说明

HashMap

ConcurrentHashMap

ConcurrentSkipListMap

跳表,支持排序

ConcurrentSkipListSet

支持排序且不允许元素重复

LinkList

ConcurrentLinkedQueue

仅支持对列头操作

LinkList

ConcurrentLinkedDequeue

支持对列头和列尾双向操作

ArrayList

CopyOnWriteArrayList

HashSet

CopyOnWriteArraySet

表 常见的非阻塞队列及其对于非安全队列

2.2 阻塞队列

阻塞队列BlockingQueue,如果其是空的,从BlockingQueue中取数据的操作将会被阻塞,进入等待状态,直到BlockingQueue中添加了元素才会被唤醒。同样,如果BlockingQueue是满的,也就是没有空余空间,试图往队列中存放元素的操作也会被阻塞,进入等待状态,直到BlockingQueue有剩余空间时才会被唤醒。

阻塞队列

说明

ArrayBlockingQueue

有界(有固定大小)阻塞队列

PriorityBlockingQueue

支持在并发情况下使用优先级队列

LinkedBlockingQueue

有界的,只支持对列头操作

LinkedBlockingDeque

有界的,支持对双端节点操作

SynchronousQueue

经常在多个线程之间传输数据

DelayQueue

延时执行任务的队列

LinkedTransferQueue

与SynchronnousQueue有些类似,其还具备嗅探功能 ,可以尝试性地添加一些数据

表 常见的阻塞队列

2.2.1 SynchronounsQueue

每一个插入操作都必须等待另一个线程的对应移除操作完成,该线程才会继续下去,否则等待。

public class SyncQueue {

    public static void main(String[] args) throws InterruptedException {
        SynchronousQueue<Integer> synchronousQueue = new SynchronousQueue<>();

        Thread putThread = new Thread(() -> {
            Random random = new Random();
            try {
                for(int i = 0; i < 5; i++) {
                    int nextInt = random.nextInt();
                    System.out.println("put:" + nextInt);
                    synchronousQueue.put(nextInt);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread takeThread = new Thread(() -> {
            try {
                for(int i = 0; i < 5; i++) {
                    System.out.println("take:" + synchronousQueue.take());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        putThread.start();
        TimeUnit.SECONDS.sleep(2);
        takeThread.start();
    }

}
/*
运行结果:
put:602390400
take:602390400
put:1015357793
put:2061181581
take:1015357793
take:2061181581
put:-1394104695
put:-292132860
take:-1394104695
take:-292132860

Process finished with exit code 0
 */

2.2.2 DelayQueue

是一个无界的BlockingQueue,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走。这种队列是有序的。

public class DelayQueueTest {

    static class Employee implements Delayed {
        private String name;
        private int age;
        private long delaySecond;

        long begin =  System.currentTimeMillis();

        public Employee(String name, int age, long delaySecond) {
            this.name = name;
            this.age = age;
            this.delaySecond = delaySecond;
        }

        //如果该方法返回延时的时间到了,就将队列的列头中的任务取出并执行
        //当返回负数,说明消息已到期,可以取出
        @Override
        public long getDelay(TimeUnit unit) {
            long toNanos = TimeUnit.SECONDS.toMillis(delaySecond);
            return toNanos + begin - System.currentTimeMillis();
        }

        //决定了在队列中的顺序
        @Override
        public int compareTo(Delayed o) {
            Employee other = (Employee) o;
            return other.age - this.age;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        DelayQueue<Employee> queue = new DelayQueue<>();
        queue.add(new Employee("小王",25,20)); //3
        queue.add(new Employee("小李", 27,19)); //1
        queue.add(new Employee("小张",21,12)); //4
        queue.add(new Employee("小美",26,4)); //2

        System.out.println("now:" + System.currentTimeMillis() / 1000);
        System.out.println(queue.take().name + ":" + System.currentTimeMillis() / 1000);
        System.out.println(queue.take().name + ":" + System.currentTimeMillis() / 1000);
        System.out.println(queue.take().name + ":" + System.currentTimeMillis() / 1000);
        System.out.println(queue.take().name + ":" + System.currentTimeMillis() / 1000);
    }

}
/*
运行结果:
now:1679070117
小李:1679070136
小美:1679070136
小王:1679070137
小张:1679070137

Process finished with exit code 0
 */

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_25308331/article/details/129630869

java并发集合有哪些_云原生手记的博客-爱代码爱编程_java并发写集合

java并发集合        数据结构(Data Structure)是编程中的基本元素,几乎每个程序都使用了一种或多种数据结构来存储和管理数据。java API提供了包含接口、类和算法的java集合框架,它实现了可用在程序中的大量数据结构。       当需要在并发程序中使用数据集合时,必须要谨慎地选择相应的实现方式。大多数集合类并不能直接用于并发

Java并发集合之List的并发集合你知道吗-爱代码爱编程

Java并发编程之-list集合的并发. 我们都知道Java集合类中的arrayList是线程不安全的。那么怎么证明是线程不安全的呢?怎么解决在并发环境下使用安全的list集合类呢? 本篇是《凯哥(凯哥Java:kagejava)并发编程学习》系列之《并发集合系列》教程的第一篇: 本文主要内容:怎么证明arrayList不是线程安全的?怎么解决这个问

java并发集合有哪些_java中常见并发集合有哪些?详细解析-爱代码爱编程

关于java中有关集合的知识点,相信大家还是有所了解的。集合中所包含的知识点是非常丰富的,而且可以细分为很多类型。今天就来为大家介绍一下并发集合的有关知识,并且用实际代码为大家展示,一起来看看吧。 首先我们需要知道的是,并发集合是jdk5.0重要的特性,增加了并发包java.util.concurrent.*。Java内存模型、volatile变量及

java 并发集合_Java并发集合-爱代码爱编程

Java并发集合 并发集合实现1 JDK1.5的出现,对于集合并发编程来说,java developer有了更多的选择。不过,在JDK1.5之前,Java也还是提供了一些解决方案。 (1)最为简单直接的就是在程序中我们自己对共享变量进行加锁。不过,缺点也显而易见,手动实现线程安全间接增加了程序的复杂度,以及代码出错的概率---例如:线程死锁的产生

java集合大全(二)并发-爱代码爱编程

Java并发集合 阻塞队列(BlockingQueue)核心方法阻塞队列类型类结构ArrayBlockingQueueDelayBlockingQueueTransferQueueLinkedTransferQueuePriorityBlockingQueueSynchronousQueue并发字典(ConcurrentHashMap)核心方法Co

java常见并发容器-爱代码爱编程

并发容器 引言 为了应对高并发过程中,数据一致性的问题,java中设计了一些并发容器。本篇将从容器的类别出发,介绍各个容器的特点及原理,为接下来的线程池做准备。 List相关 Vector Vector是最古老的并发容器,其实现了List接口,方法都是默认加synchronized的,所以效率很低,现在基本不会用它。 示例 用到的锁 sync

jvm监控搭建-爱代码爱编程

文章目录 JVM监控搭建整体架构JolokiaTelegrafInfluxdbGrafana JVM监控搭建 整体架构 JVM 的各种内存信息,会通过 JMX 接口进行暴露。 Jolokia

redisson项目地址-爱代码爱编程

github 项目 https://github.com/redisson/redisson 整合 spring boot 使用 https://github.com/redisson/redisson/tree/master/redisson-spring-boot-starter#spring-boot-starter 对应配置类以

hbase-爱代码爱编程

1、 简介 跳跃表(SkipList)是一种能高效实现插入、删除、查找的内存数据结构,这些操作的期望复杂度都是O(logN)。与红黑树以及其他的二分查找树相比,跳跃表的优势在于实现简单,而且在并发场景下加锁粒度更小,