zoukankan      html  css  js  c++  java
  • 【多线程】JUC 类总览

    1.   Java并发知识库

    ForkJoinPool:Since 1.7

    CompletableFuture:1.8

     

     

    20个使用 Java CompletableFuture的例子

    https://colobu.com/2018/03/12/20-Examples-of-Using-Java%E2%80%99s-CompletableFuture/

     

    JAVA线程实现/创建方式

    2.1 继承Thread类

     2.2 实现Runnable接口 

     2.3 ExecutorService、Callable、Future有返回值线程

      有返回值的任务必须实现Callable接口,无返回值的任务必须Runnable接口。

      执行Callable任务后,可以获取一个Future的对象,在该对象上调用get就可以获取到Callable任务返回的Object。

      再结合线程池接口ExecutorService就可以实现传说中有返回结果的多线程了。 

    // 创建一个线程池 
    ExecutorService pool = Executors.newFixedThreadPool(taskSize); 
    // 创建多个有返回值的任务 
    List<Future> list = new ArrayList<Future>(); 
    for (int i = 0; i < taskSize; i++) { 
        Callable c = new MyCallable(i + " "); 
        // 执行任务并获取Future对象
        Future f = pool.submit(c); 
        list.add(f); 
       } 
       // 关闭线程池 
       pool.shutdown(); 
       // 获取所有并发任务的运行结果 
       for (Future f : list) { 
        // 从Future对象上获取任务的返回值,并输出到控制台
         System.out.println("res:" + f.get().toString()); 
    }

     

    3.   四种线程池

      Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService 

     newCachedThreadPool

      创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。

     newFixedThreadPool

      创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在

     newScheduledThreadPool

      创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

     newSingleThreadExecutor

      xecutors.newSingleThreadExecutor()返回一个线程池(这个线程池只有一个线程),这个线程池可以在线程死后(或发生异常时)重新启动一个线程来替代原来的线程继续执行下去 !


    使用退出标志退出线程 (翻译自jdk.chm

     方法:isInterrupted(): 返回当前中断标记

       方法:interrupt():interrupt()的作用是中断本线程。处理结果区分当前业务线程的状态

      本线程中断自己是被允许的;其它线程调用本线程的interrupt()方法时,会通过checkAccess()检查权限。这有可能抛出SecurityException异常。
      如果本线程是处于阻塞状态:调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态,或者调用线程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也会让它进入阻塞状态。若线程在阻塞状态时,调用了它的interrupt()方法,那么它的“中断状态”会被清除并且会收到一个InterruptedException异常。例如,线程通过wait()进入阻塞状态,此时通过interrupt()中断该线程;调用interrupt()会立即将线程的中断标记设为“true”,但是由于线程处于阻塞状态,所以该“中断标记”会立即被清除为“false”,同时,会产生一个InterruptedException的异常。
      如果线程被阻塞在一个Selector选择器中,那么通过interrupt()中断它时;线程的中断标记会被设置为true,并且它会立即从选择操作中返回。
      如果不属于前面所说的情况(比如正常的业务处理)那么通过interrupt()中断线程时,它的中断标记会被设置为“true”。
      中断一个“已终止的线程”不会产生任何操作。

    public class Main {
        public static void main(String[] args) {
            TestThread testThread = new TestThread();
            testThread.start();
    
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            testThread.interrupt();  //  此时业务线程正在sleep状态,所以最终打印 TestRunner is interrupted by InterruptedException; 
        }
    }
    
    public class TestThread extends Thread {
        @Override
        public void run() {
            try {
                while (!isInterrupted()) {
                    Thread.sleep(2000L);
                    for (int i = 0; i < 100000; i++) {
    
                    }
                }
                System.out.println("TestRunner exited by isInterrupted flag");  // 如果业务在执行for循环时被中断,则标记位=true,所以while循环退出,最终打印左侧语句
    
            } catch (InterruptedException e) {
                System.out.println("TestRunner is interrupted by InterruptedException");
            }
        }
    }

    sleep与wait 区别

    1.  对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
    2.  sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
    3.  在调用sleep()方法的过程中,线程不会释放对象锁。
    4.  而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。 

    JAVA后台线程:如JVM垃圾回收线程

  • 相关阅读:
    C4.5算法的学习笔记
    jQuery学习笔记(二)jQuery中DOM操作
    jQuery学习笔记(四)jQuery中的动画
    jQuery学习笔记(一)jQuery选择器
    编译JDK源代码,开启Debug信息[转]
    【转】如何debug没有源代码的class文件——eclipse+jad
    【转】JAVA的内省(introspector)与反射(reflection)
    Java中访问修饰符protected的权限 [转]
    [转]我是如何设计并实现一门程序设计语言——一门函数式编程语言Lucida的诞生
    不断重构
  • 原文地址:https://www.cnblogs.com/clarino/p/12727885.html
Copyright © 2011-2022 走看看