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源码
当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
网友评论