美文网首页
多线程问题总结

多线程问题总结

作者: 定金喜 | 来源:发表于2020-02-04 17:16 被阅读0次

    1.实现多线程的方式

    a.实现Runnable接口

    package com.dxc;
    
    /**
     * @Author: ding
     * @Date: 2020-01-28 15:56
     */
    public class RunnableTest implements Runnable{
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    
        public static void main(String[] args) {
            RunnableTest threadTest = new RunnableTest();
            for(int i=0;i<10; i++) {
                Thread thread = new Thread(threadTest);
                thread.start();
            }
        }
    }
    

    输出:

    Thread-0
    Thread-1
    Thread-2
    Thread-3
    Thread-4
    Thread-5
    Thread-6
    Thread-7
    Thread-8
    Thread-9
    

    b.继承Thread类

    package com.dxc;
    
    /**
     * @Author: ding
     * @Date: 2020-01-28 16:18
     */
    public class ThreadTest extends Thread{
    
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
        public static void main(String[] args) {
            for(int i=0; i<10; i++) {
                ThreadTest threadTest = new ThreadTest();
                threadTest.start();
            }
        }
    }
    

    输出:

    Thread-0
    Thread-1
    Thread-2
    Thread-3
    Thread-4
    Thread-5
    Thread-6
    Thread-7
    Thread-8
    Thread-9
    

    c.实现Callable接口

    package com.dxc;
    
    import java.util.concurrent.Callable;
    import java.util.concurrent.FutureTask;
    
    /**
     * @Author: ding
     * @Date: 2020-01-28 16:39
     */
    public class CallableTest implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            Integer total = 0;
            for(int i=1; i<=100; i++) {
                total += i;
            }
            return total;
        }
    
        public static void main(String[] args) throws Exception{
    
            CallableTest callableTest = new CallableTest();
            FutureTask<Integer> futureTask = new FutureTask(callableTest);
            for (int i=0; i<10; i++) {
                Thread thread = new Thread(futureTask);
                thread.start();
            }
        }
    }
    

    2.线程状态以及相互转换

    线程流转状态图1
    线程流转状态图2
    线程流转状态图3

    New:新建状态,Thread thread = new Thread()
    Runnable:可执行状态,执行thread.start()后;
    Running:正在执行线程代码段
    Blocked:阻塞状态,执行到Synchronized代码段时,竞争同步锁
    Waiting:执行wait,join,park和await后
    Time_waiting:执行带超时时间的sleep,wait,join,park和await函数
    Terminated:执行结束

    3.jstack线程堆栈中的状态有哪些

    例子:

    package com.dxc;
    /**
     * @Author: ding
     * @Date: 2020-01-28 16:18
     */
    public class ThreadTest extends Thread{
        /**
         * 0 time_waiting
         * 1 running
         * 2 waiting
         */
        private Integer type;
        private SubThread subThread;
    
        @Override
        public synchronized void  run(){
            switch (type){
                case 0:
                    try {
                        Thread.sleep(60000);
                    } catch (Exception ex) {
    
                    }
                    break;
                case 1:
                    while (true){
                        for(int i=0; i < 1000000000000000L; i++) {
                            for(int j=0; j < 10000000000L; j++) {
                                System.out.println("111");
                            }
                        }
                    }
                case 2:
                    waiting();
                    break;
                case 3:
                    subThread.blockTest();
                    break;
            }
        }
    
        public static class SubThread {
            public synchronized void blockTest() {
                try {
                    Thread.sleep(60000);
                } catch (Exception ex) {
    
                }
            }
        }
    
        public synchronized void waiting() {
            try {
                wait();
            }catch (Exception ex){
            }
        }
    
        public static void main(String[] args) {
    
            ThreadTest thread1 = new ThreadTest();
            thread1.setName("xiancheng1");
            thread1.type = 0;
            thread1.start();
    
            ThreadTest thread2 = new ThreadTest();
            thread2.setName("xiancheng2");
            thread2.type = 1;
            thread2.start();
    
            ThreadTest thread3 = new ThreadTest();
            thread3.setName("xiancheng3");
            thread3.type = 2;
            thread3.start();
    
            SubThread subThread = new SubThread();
    
            ThreadTest thread4 = new ThreadTest();
            thread4.subThread = subThread;
            thread4.setName("xiancheng4");
            thread4.type = 3;
            thread4.start();
    
            ThreadTest thread5 = new ThreadTest();
            thread5.subThread = subThread;
            thread5.setName("xiancheng5");
            thread5.type = 3;
            thread5.start();
        }
    }
    

    执行jstack的结果:

    "Attach Listener" #17 daemon prio=9 os_prio=31 tid=0x00007f85c6405800 nid=0x5c03 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "DestroyJavaVM" #16 prio=5 os_prio=31 tid=0x00007f85c501a000 nid=0x2503 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "xiancheng5" #15 prio=5 os_prio=31 tid=0x00007f85c3014000 nid=0x5b03 waiting for monitor entry [0x00007000032c4000]
       java.lang.Thread.State: BLOCKED (on object monitor)
        at com.dxc.ThreadTest$SubThread.blockTest(ThreadTest.java:49)
        - waiting to lock <0x000000076f4808a0> (a com.dxc.ThreadTest$SubThread)
        at com.dxc.ThreadTest.run(ThreadTest.java:40)
        - locked <0x000000076f480720> (a com.dxc.ThreadTest)
    
    "xiancheng4" #14 prio=5 os_prio=31 tid=0x00007f85c681e000 nid=0xa603 waiting on condition [0x00007000031c1000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.dxc.ThreadTest$SubThread.blockTest(ThreadTest.java:49)
        - locked <0x000000076f4808a0> (a com.dxc.ThreadTest$SubThread)
        at com.dxc.ThreadTest.run(ThreadTest.java:40)
        - locked <0x000000076f488588> (a com.dxc.ThreadTest)
    
    "xiancheng3" #13 prio=5 os_prio=31 tid=0x00007f85c5019000 nid=0xa703 in Object.wait() [0x00007000030be000]
       java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076f498000> (a com.dxc.ThreadTest)
        at java.lang.Object.wait(Object.java:502)
        at com.dxc.ThreadTest.waiting(ThreadTest.java:58)
        - locked <0x000000076f498000> (a com.dxc.ThreadTest)
        at com.dxc.ThreadTest.run(ThreadTest.java:37)
        - locked <0x000000076f498000> (a com.dxc.ThreadTest)
    
    "xiancheng2" #12 prio=5 os_prio=31 tid=0x00007f85c5010000 nid=0x5703 runnable [0x0000700002fbb000]
       java.lang.Thread.State: RUNNABLE
        at java.io.FileOutputStream.writeBytes(Native Method)
        at java.io.FileOutputStream.write(FileOutputStream.java:326)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        - locked <0x000000076f4d1a30> (a java.io.BufferedOutputStream)
        at java.io.PrintStream.write(PrintStream.java:482)
        - locked <0x000000076f484ab0> (a java.io.PrintStream)
        at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
        at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
        at sun.nio.cs.StreamEncoder.flushBuffer(StreamEncoder.java:104)
        - locked <0x000000076f484a70> (a java.io.OutputStreamWriter)
        at java.io.OutputStreamWriter.flushBuffer(OutputStreamWriter.java:185)
        at java.io.PrintStream.newLine(PrintStream.java:546)
        - eliminated <0x000000076f484ab0> (a java.io.PrintStream)
        at java.io.PrintStream.println(PrintStream.java:807)
        - locked <0x000000076f484ab0> (a java.io.PrintStream)
        at com.dxc.ThreadTest.run(ThreadTest.java:32)
        - locked <0x000000076f4808b0> (a com.dxc.ThreadTest)
    
    "xiancheng1" #11 prio=5 os_prio=31 tid=0x00007f85c3013000 nid=0xa903 waiting on condition [0x0000700002eb8000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
        at java.lang.Thread.sleep(Native Method)
        at com.dxc.ThreadTest.run(ThreadTest.java:23)
        - locked <0x000000076f490178> (a com.dxc.ThreadTest)
    
    "Service Thread" #10 daemon prio=9 os_prio=31 tid=0x00007f85c483a000 nid=0x4003 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C1 CompilerThread3" #9 daemon prio=9 os_prio=31 tid=0x00007f85c580a800 nid=0x4103 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C2 CompilerThread2" #8 daemon prio=9 os_prio=31 tid=0x00007f85c580a000 nid=0x4203 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C2 CompilerThread1" #7 daemon prio=9 os_prio=31 tid=0x00007f85c5809000 nid=0x3c03 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "C2 CompilerThread0" #6 daemon prio=9 os_prio=31 tid=0x00007f85c63ff800 nid=0x3b03 waiting on condition [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Monitor Ctrl-Break" #5 daemon prio=5 os_prio=31 tid=0x00007f85c63fe800 nid=0x4503 runnable [0x00007000027a3000]
       java.lang.Thread.State: RUNNABLE
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
        at java.net.SocketInputStream.read(SocketInputStream.java:171)
        at java.net.SocketInputStream.read(SocketInputStream.java:141)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
        - locked <0x000000076f48ecd8> (a java.io.InputStreamReader)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:161)
        at java.io.BufferedReader.readLine(BufferedReader.java:324)
        - locked <0x000000076f48ecd8> (a java.io.InputStreamReader)
        at java.io.BufferedReader.readLine(BufferedReader.java:389)
        at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)
    
    "Signal Dispatcher" #4 daemon prio=9 os_prio=31 tid=0x00007f85c4826800 nid=0x3903 runnable [0x0000000000000000]
       java.lang.Thread.State: RUNNABLE
    
    "Finalizer" #3 daemon prio=8 os_prio=31 tid=0x00007f85c380b000 nid=0x4c03 in Object.wait() [0x000070000259d000]
       java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076f498180> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:144)
        - locked <0x000000076f498180> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:165)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:216)
    
    "Reference Handler" #2 daemon prio=10 os_prio=31 tid=0x00007f85c3003800 nid=0x4e03 in Object.wait() [0x000070000249a000]
       java.lang.Thread.State: WAITING (on object monitor)
        at java.lang.Object.wait(Native Method)
        - waiting on <0x000000076f490a68> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:502)
        at java.lang.ref.Reference.tryHandlePending(Reference.java:191)
        - locked <0x000000076f490a68> (a java.lang.ref.Reference$Lock)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)
    .......
    

    主要状态有:
    WAITING,TIME_WAITING,RUNNABLE,BLOCKED 。

    4.线程池

    参考:https://baijiahao.baidu.com/s?id=1637828094805085849&wfr=spider&for=pc
    a.线程池主要参数
    1.corePoolSize:核心线程数
    核心线程会一直存活,即使没有任务要执行
    当线程数小于核心线程数,即使有线程空闲,线程池也会优先创建新线程处理
    如果设置allowCoreThreadTimeout=true(默认false),核心线程池也会超时关闭,核心线程数会变为0
    2.queueCapacity:任务队列容量(阻塞)
    当核心线程数达到最大时,新任务会放在任务队列中排队消费执行
    3.keepAliveTime:线程空闲时间
    当线程空闲时间超过keepAliveTime就释放线程,一直到线程数量=corePoolSize
    如果allowCoreThreadTimeout=true,则会直到线程数量=0
    4.allowCoreThreadTimeout:是否允许核心线程超时
    true:允许核心线程池超时,任务执行完后,线程数量会变为0
    false:不允许核心线程池超时,任务执行完后,线程数量不会变为0(核心线程数量>0前提)
    5.maxPoolSize:最大线程数量
    当线程数>=corePoolSize,且任务队列已满时,线程池会创建新线程来处理任务;
    当线程数=maxPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常
    6.rejectedExecutionHandler:任务拒绝处理器
    两种情况会拒绝处理任务:(1)当线程数已经达到maxPoolSize,切队列已满,会拒绝新任务。(2)当线程池被调用shutdown()后,会等待线程池里的任务执行完毕,再shutdown。如果在调用shutdown()和线程池真正shutdown之间提交任务,会拒绝新任务。线程池会调用rejectedExecutionHandler来处理这个任务。如果没有设置默认是AbortPolicy,会抛出异常。
    b.线程池拒绝策略
    (1)AbortPolicy 丢弃任务,抛出RejectedExecutionException异常
    (2)DiscardPolicy 丢弃任务,不抛出异常
    (3)DiscardOldestPolicy 丢弃任务队列中最先入队的任务
    (4)CallerRunsPolicy 执行任务
    c.线程池的执行过程
    1.当线程数小于核心线程数时,创建新线程;
    2.当线程数大于或者等于核心线程数,且任务队列未满时,将任务放进任务队列待执行;
    3.当线程数大于或者等于核心线程数,且任务队列已满。(1)若线程数小于最大线程数,创建新线程;(2)若线程数大于或者等于最大线程数时,根据拒绝策略进行处理
    d.线程执行过程中失败的处理方式
    先看ThreadPoolExecutor源码

    线程池代码片段1
    当task.run() 也就是执行线程任务出现异常时,直接捕获然后抛出,此时按照提交线程的方式,会有两种不同的情况:
    (1)调用execute方法提交:
    线程池代码片段2
    未对command做任何封装,所以线程执行发生异常,会导致runWorker函数跳出while循环,completedAbruptly为true,然后看processWorkerExit函数,此函数的处理逻辑:
    线程池代码片段3
    代码段逻辑是删除掉异常的线程,并重新创建线程放入线程池。
    (2)调用submit方法提交:
    线程池代码片段4
    会对task进行封装,看封装函数newTaskFor,最终进入到FutureTask类,看其run函数:
    线程池代码片段5
    这里对线程的异常进行了捕获,但是未抛出,所以这种提交方式线程不会抛出异常,callable其实跟踪源码可以看到使用了适配器模式,将Runnable接口的run方法适配到Callable接口的call方法,适配器类如下所示:
    线程池代码片段6

    相关文章

      网友评论

          本文标题:多线程问题总结

          本文链接:https://www.haomeiwen.com/subject/kzxmthtx.html