乐趣区

JAVA多线程并发

线程状态图

图来自 Java 线程的 6 种状态及切换(透彻解说)

初始、就绪、运行、期待、阻塞(synchronized)、终止。

Thread.sleep(millis)肯定工夫后主动复原执行,不开释对象锁
Object.wait() 间接 开释锁 ,始终期待,晓得 notify()唤醒。
Thread1.join() 示意运行的线程阻塞本人,期待 Thread1 执行完,再执行上面语句。
yield()让出 cpu,不开释对象锁,进入就绪态, 随时可能再次运行。

只有运行态和就绪态之间波及到 CPU 资源的切换。(即 yield())

Thread 开启的 3 种形式
Thread、Runnable、Callable

  • Thread
    最简略的一种,间接继承 Thread,重写 run 办法。主类中 new ThreadName().start(); 则进去就绪态。
  • Runnable

    • 实现 Runnable 接口,重写 run。主类中 new RunnableName().start();
    • 实现 Runnable 接口,重写 run。主类中 new Thread(new Runnable()).start();
    • Thread 类还有其余重载办法,如传入 ThreadGoup,Runnable 初始执行接口等等,以上两个最罕用。

    Thread 类也是实现了 Runnable 接口,实际上都是调用的 Runnable 接口的 run()办法。

  • Callable
    实现 Callable 接口,重写 call()办法。创立 FutureTask 对象 new FutureTask<>(CallableName); 再 new Thread(FutureTak).start(); 即可。FutureTask 间接实现了 Runnable 和 Future,所以理论调用的还是 Thread(Runnable)构造方法。

    Callable 接口只有一个办法 V call();
    Future 接口蕴含 cancel、isCancelled、isDone、get 办法,用户获取返回值。(Futuretask 对 Future 接口中的办法进行了重写)

Executor 治理线程

  • newFixedThreadPool 固定大小的线程池
  • newCachedThreadPool 可扩大的
  • newScheduledThreadPool 可调度的, 运行一次,反复运行等
  • newSingleThreadPool 单线程池
  • newWorkStealingPool 窃取别的线程池的线程

应用:

ExecutorService executor = Executors.newFixedThreadPool(3);
Future<String> future = excutor.submit(Callable);// 退出线程池
future.get();// 获取返回值

后盾线程 deamon
定义:程序运行时在后盾提供通用服务的线程,这种线程并不属于不可或缺的局部。后盾线程运行的前提是必须有至多一个非后盾线程运行。

Thread.setDeamon(ture); 必须在 start()前设置。

java.util.concurrent 包

  • CountDownLatch
    同步多个工作,能够设置一个初值,任何在这个对象上调用 wait()都将被阻塞,晓得值变成 0,每个工作执行完调用 countDown 都使值减 1。

    初始值不能重置,只能始终减上来。CyclicBarrier 能够重置。

  • CyclicBarrier
    用于并发工作期待(相似 join),如:idm 多线程下载文件,最初进行文件整顿。能够重置初始值。
  • DelayedQueue
    用于延时队列(延时取出元素),队头的提早最长。
  • PriorityBlockingQueue
    优先级阻塞队列
  • SemaPhore
    信号量,容许 n 个工作同时拜访。

平安失败的原理
就是 CopyOnWriteArrayList 办法。

java.util.concurrent 包上面的所有的类都是平安失败的
疾速失败的异样:ConcurrentModificationException
乐观锁: version、CAS(compareAndSwap)(Atomic 包、ReentrankLock 就是具体实现)
乐观锁: synchroinized


java.nio.*
基于缓冲的流。
次要组成:Channel,Buffer,Selector

clear,flip,compact 区别:

ByteBuffer 中有 pos、lim、cap 来记录缓冲应用状况。

  • clear:position=0,limit=capacity,【清空缓冲】
  • flip:limit=postion;position=0;【读指针挪动缓冲头】
  • compact: 未读完的数据,压缩到缓冲头。【压缩未读完数据】

整体流程:获取通道,调配缓冲,clear,read 一次,{flip, 解决读到的数据,compact,read 一次}

大括号 {} 中示意循环执行。
读的模板代码如下,根本大同小异。

void fileChannel(){
        try {FileInputStream fis = new FileInputStream("content.txt");
            FileChannel channel = fis.getChannel();
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);// 调配缓冲
            //position 置为 0,limit 置为 capacity
            byteBuffer.clear();     
            int read = channel.read(byteBuffer);
            System.out.println(byteBuffer);
            while (read!=-1){
            //limit 置成 position 最初的位值, 再指针 position 调成 0
            // 从头读。(position、capacity、limit)
                byteBuffer.flip();          
                while(byteBuffer.hasRemaining()){System.out.print((char)byteBuffer.get());
                }
                // 把未读完的数据压缩至 0 -position,// 下一次从 position 到 limit 读
                byteBuffer.compact();       
                read=channel.read(byteBuffer);
            }
            channel.close();
            fis.close();}catch (IOException e){e.printStackTrace();
        }
    }

fileChannel 还有 tryLock(),lock()和 release()办法。tryLock 为非阻塞式,得不到锁就立马返回

IO 多路复用——selector【NIO 的重点】
一个选择器治理多个 Channel。

举荐优良博客:NIO 的三大组件

退出移动版