====== 多线程编程核心技术整理 ======
===== 前言 =====
2016年5月12日东哥在微信读书APP上送给我一本书《JAVA多线程编程核心技术》,作者高洪岩。在接下来的7天内读完了,感觉这本书写的挺好,作者基本把所有的知识点都结合代码例子来讲解,容易被程序员接受。其实在读的过程当中,就想着要把这本书的知识点做个整理,用于备忘也用于更好的掌握多线程。可能在我尝试整理知识点的时候,某些我觉得比较不常用的,我会比较简单的整理。
===== 多线程基础 =====
==== 进程和多线程的概念及线程的优点 ====
* 进程
比如WINDOWS任务管理器里,看到的QQ.EXE,就是一个进程
* 线程
比如QQ中的视频,发送文件,发送文字图片等,都是独立在运作的“线程”
* 线程的优点
多线程或者说多任务操作系统,可以最大限度地利用CPU的空闲时间在不同的任务之间不停的切换,由于切换的速度非常快,使使用者感觉多个任务是在同时进行的。当然后来也出现多个CPU,或者一个CPU多核就是为了加快机器运算。
==== 使用多线程 ====
=== 打印主线程的名字 ===
package com.gxx.threads.study.test1;
/**
* 测试类-打印主线程的名字
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
/**
* 打印main方法当前线程名字
* 输出:main
*/
System.out.println(Thread.currentThread().getName());
}
}
输出
main
=== 两种实现线程类的方法 ===
* 继承Thread实现线程类
package com.gxx.threads.study.test2;
/**
* 继承Thread实现线程类
* @author Gxx
*/
public class MyThread1 extends Thread {
/**
* 覆盖Thread中的run方法
*/
@Override
public void run() {
System.out.println("MyThread1.run()");
}
}
* 实现Runnable实现线程类
package com.gxx.threads.study.test2;
/**
* 实现Runnable实现线程类
* @author Gxx
*/
public class MyThread2 implements Runnable {
/**
* 实现Runnable中的run方法
*/
@Override
public void run() {
System.out.println("MyThread2.run()");
}
}
* 两种实现的区别
本质上并没有什么区别,但是由于JAVA只支持单继承,如果继承了Thread就不能继承其它的父类了,所以绝大多数情况下是由于这个,而Thread类其实也实现了Runnable接口。
=== 测试start()、run()和多次start() ===
* start()
start()通过“线程规划器”此线程已经准备就绪,等待调用run(),CPU在不确定的时间调用run()
* run()
直接执行run,就不是“线程规划器”来调度了,而是执行run()的当前线程直接调用方法,如果是main()中调用,则当前线程就是main
* 多次start()
多次start()会抛出异常java.lang.IllegalThreadStateException,报线程状态异常
package com.gxx.threads.study.test3;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 构造方法
*/
public MyThread(){
System.out.println("线程[" + Thread.currentThread().getName() + "]执行构造方法");
}
/**
* 覆盖run方法
*/
@Override
public void run() {
System.out.println("线程[" + Thread.currentThread().getName() + "]执行run");
}
}
package com.gxx.threads.study.test3;
/**
* 测试类-测试start和run和多次start
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.setName("线程A");//设置线程名字
thread.run();
thread.start();
thread.start();
}
}
输出
线程[main]执行构造方法
线程[main]执行run
线程[线程A]执行run
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:705)
at com.gxx.threads.study.test3.Test.main(Test.java:17)
=== 不共享变量,线程安全 ===
package com.gxx.threads.study.test4;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 计数
*/
int count = 10;
/**
* 覆盖run方法
*/
@Override
public void run() {
System.out.println("线程[" + Thread.currentThread().getName() + "]执行count=" + (count--));
}
}
package com.gxx.threads.study.test4;
/**
* 测试类-不共享变量,线程安全
* @author Gxx
*/
public class TestSafe {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
MyThread thead1 = new MyThread();
MyThread thead2 = new MyThread();
MyThread thead3 = new MyThread();
MyThread thead4 = new MyThread();
MyThread thead5 = new MyThread();
MyThread thead6 = new MyThread();
MyThread thead7 = new MyThread();
MyThread thead8 = new MyThread();
MyThread thead9 = new MyThread();
MyThread thead10 = new MyThread();
thead1.start();
thead2.start();
thead3.start();
thead4.start();
thead5.start();
thead6.start();
thead7.start();
thead8.start();
thead9.start();
thead10.start();
}
}
输出
线程[Thread-0]执行count=10
线程[Thread-2]执行count=10
线程[Thread-1]执行count=10
线程[Thread-3]执行count=10
线程[Thread-4]执行count=10
线程[Thread-5]执行count=10
线程[Thread-6]执行count=10
线程[Thread-7]执行count=10
线程[Thread-8]执行count=10
线程[Thread-9]执行count=10
=== 共享变量,线程不安全 ===
package com.gxx.threads.study.test4;
/**
* 测试类-共享变量,线程不安全
* @author Gxx
*/
public class TestNotSafe {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
MyThread thread = new MyThread();
Thread thead1 = new Thread(thread);
Thread thead2 = new Thread(thread);
Thread thead3 = new Thread(thread);
Thread thead4 = new Thread(thread);
Thread thead5 = new Thread(thread);
Thread thead6 = new Thread(thread);
Thread thead7 = new Thread(thread);
Thread thead8 = new Thread(thread);
Thread thead9 = new Thread(thread);
Thread thead10 = new Thread(thread);
thead1.start();
thead2.start();
thead3.start();
thead4.start();
thead5.start();
thead6.start();
thead7.start();
thead8.start();
thead9.start();
thead10.start();
}
}
输出
线程[Thread-2]执行count=10
线程[Thread-3]执行count=9
线程[Thread-1]执行count=10
线程[Thread-4]执行count=8
线程[Thread-5]执行count=7
线程[Thread-6]执行count=6
线程[Thread-7]执行count=5
线程[Thread-8]执行count=4
线程[Thread-9]执行count=3
线程[Thread-10]执行count=2
=== 共享变量,使用synchronized使得线程安全 ===
package com.gxx.threads.study.test5;
/**
* 工具类
* @author Gxx
*/
public class Tools {
/**
* 计数
*/
int count = 10;
/**
* 打印count
* @throws Exception
*/
public synchronized void printCount() {
try {
count--;
/**
* 睡眠1秒
*/
Thread.sleep(1000);
System.out.println("线程[" + Thread.currentThread().getName() + "]执行count=" + count);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package com.gxx.threads.study.test5;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 工具类
*/
Tools tools;
/**
* 构造方法
* @param tools
*/
public MyThread(Tools tools){
this.tools = tools;
}
/**
* 覆盖父类的run方法
*/
@Override
public void run() {
tools.printCount();
}
}
package com.gxx.threads.study.test5;
/**
* 测试类-共享变量,使用synchronized使得线程安全
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
Tools tools = new Tools();
/**
* 共用同一个tools
*/
MyThread thread1 = new MyThread(tools);
MyThread thread2 = new MyThread(tools);
thread1.start();
thread2.start();
}
}
输出
线程[Thread-0]执行count=9
线程[Thread-1]执行count=8
=== count--和System.out.println() ===
注意:
* count--不是同步的,分三步1.获取count的值;2.count-1;3.再赋值给count;不同步则有时间差
* System.out.println()是同步的
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
==== getId()、isAlive()和sleep() ====
* getId 是取得线程的唯一标识
* isAlive是判断当前线程是否处于活动状态
* sleep是指this.currentThread()休眠多少毫秒
package com.gxx.threads.study.test6;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 覆盖run方法
*/
@Override
public void run() {
System.out.println("线程 run 开始 时间=" + System.currentTimeMillis());
System.out.println("线程 getId()=" + this.getId());
System.out.println("线程 run 中 isAlive()=" + this.isAlive());
System.out.println("线程 run 结束 时间=" + System.currentTimeMillis());
}
}
package com.gxx.threads.study.test6;
/**
* 测试类-测试getId()、isAlive()和sleep()
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main主线程 开始 时间=" + System.currentTimeMillis());
System.out.println("main主线程 getId()=" + Thread.currentThread().getId());
MyThread thread = new MyThread();
System.out.println("线程 start前 isAlive()=" + thread.isAlive());
thread.start();
System.out.println("线程 start后 isAlive()=" + thread.isAlive());
System.out.println("main主线程 结束 时间=" + System.currentTimeMillis());
try {
Thread.sleep(1000);
System.out.println("main主线程 sleep(1秒)后 线程 isAlive=" + thread.isAlive());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出
main主线程 开始 时间=1464492826078
main主线程 getId()=1
线程 start前 isAlive()=false
线程 start后 isAlive()=true
main主线程 结束 时间=1464492826080
线程 run 开始 时间=1464492826080
线程 getId()=8
线程 run 中 isAlive()=true
线程 run 结束 时间=1464492826080
main主线程 sleep(1秒)后 线程 isAlive=false
==== 停止线程 ====
=== interrupt、isInterrupted、interrupted ===
* interrupt
给线程打个中断的标记,线程继续运行
* isInterrupted
判断线程是否有中断的标记,如果有返回true,多次调用都返回true
* interrupted
静态方法,Thread.interrupted(),判断当前线程是否有中断的标记,如果有返回true,并清空该标记,下次再执行,则返回false
package com.gxx.threads.study.test7;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 覆盖run方法
*/
@Override
public void run() {
System.out.println("run 开始");
this.interrupt();
System.out.println("执行this.interrupt()只是打个线程中断标记,线程还是继续往下走");
System.out.println("this.isInterrupted()=" + this.isInterrupted());
System.out.println("this.isInterrupted()=" + this.isInterrupted());
System.out.println("执行静态方法Thread.interrupted()=" + Thread.interrupted() + "后清空中断状态");
System.out.println("再执行静态方法Thread.interrupted()=" + Thread.interrupted());
System.out.println("this.isInterrupted()=" + this.isInterrupted());
System.out.println("run 结束");
}
}
package com.gxx.threads.study.test7;
/**
* 测试类-测试interrupt、isInterrupted、interrupted
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
MyThread thread = new MyThread();
thread.start();
System.out.println("main 结束");
}
}
输出
main 开始
main 结束
run 开始
执行this.interrupt()只是打个线程中断标记,线程还是继续往下走
this.isInterrupted()=true
this.isInterrupted()=true
执行静态方法Thread.interrupted()=true后清空中断状态
再执行静态方法Thread.interrupted()=false
this.isInterrupted()=false
run 结束
=== 测试线程interrupt()然后sleep() ===
先中断,再睡眠,会抛出异常
package com.gxx.threads.study.test8;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 覆盖run方法
*/
@Override
public void run() {
System.out.println("run 开始");
System.out.println("run 准备执行sleep(1000) 睡眠1秒");
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("run 结束");
}
}
package com.gxx.threads.study.test8;
/**
* 测试类-测试线程interrupt()然后sleep()
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
MyThread thread = new MyThread();
thread.start();
thread.interrupt();
System.out.println("main 执行thread.interrupt(),给thread打个中断标记");
System.out.println("main 结束");
}
}
输出
main 开始
main 执行thread.interrupt(),给thread打个中断标记
main 结束
run 开始
run 准备执行sleep(1000) 睡眠1秒
run 结束
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.gxx.threads.study.test8.MyThread.run(MyThread.java:16)
=== 测试线程sleep()然后interrupt() ===
在睡眠的过程中,中断,会抛出异常
package com.gxx.threads.study.test9;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 覆盖run方法
*/
@Override
public void run() {
System.out.println("run 开始");
System.out.println("run 准备执行sleep(10000) 睡眠10秒");
try {
sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("run 结束");
}
}
package com.gxx.threads.study.test9;
/**
* 测试类-测试线程sleep()然后interrupt()
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
MyThread thread = new MyThread();
thread.start();
System.out.println("main 睡眠1秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main 执行thread.interrupt(),给thread打个中断标记");
thread.interrupt();
System.out.println("main 结束");
}
}
输出
main 开始
main 睡眠1秒
run 开始
run 准备执行sleep(10000) 睡眠10秒
main 执行thread.interrupt(),给thread打个中断标记
main 结束
run 结束
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at com.gxx.threads.study.test9.MyThread.run(MyThread.java:16)
=== 抛出异常或者return来停止线程 ===
建议使用这两种方式
if(this.isInterrupted()){
throw new Exception();
}
if(this.interrupted()){
return;
}
=== stop()暴力停止,@Deprecated作废 ===
不建议使用,因为stop()停止线程有可能使一些清理性的工作得不到完成。另外会对锁定的对象强制解锁,导致数据得不到同步的处理,出现数据不一致的问题!比如:
synchronized public void setUserNameAndPassword(String userName, String password){
this.userName = userName;
Thread.sleep(1000000);//正好外面执行stop(),导致数据不一致
this.password = password;
}
==== suspend()和resume() ====
* suspend()暂停
如果synchronized方法执行一半,不会释放锁,一直卡着,比如线程内System.out.println()打印一半(打印数据,再打印换行,有synchronized代码块)暂停了,其他地方调System.out.println()都会一直卡着,输出不到控台;@Deprecated作废,不建议使用
* resume()恢复
从暂停的地方恢复,程序往下走,但是有时间差,可能会有脏数据;@Deprecated作废,不建议使用
package com.gxx.threads.study.test10;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 标志
*/
boolean flag = false;
/**
* 覆盖run方法
*/
@Override
public void run() {
System.out.println("run 开始");
System.out.println("run 打印flag=" + flag);
System.out.println("run 执行this.suspend(),并等待resume()");
this.suspend();
System.out.println("run 线程被恢复");
System.out.println("run 再次打印flag=" + flag);
System.out.println("run 结束");
}
}
package com.gxx.threads.study.test10;
/**
* 测试类-测试线程suspend()和resume(),产生脏数据
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
MyThread thread = new MyThread();
thread.start();
System.out.println("main 睡眠1秒");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main 睡眠1秒后 修改thread.flag = true");
thread.flag = true;
System.out.println("main 执行thread.resume()");
thread.resume();
System.out.println("main 结束");
}
}
输出
main 开始
main 睡眠1秒
run 开始
run 打印flag=false
run 执行this.suspend(),并等待resume()
main 睡眠1秒后 修改thread.flag = true
main 执行thread.resume()
main 结束
run 线程被恢复
run 再次打印flag=true
run 结束
==== yield() ====
让出CPU资源,但是有可能让出又马上获得CPU时间片。
package com.gxx.threads.study.test11;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 计数
*/
int count = 10;
/**
* 覆盖run方法
*/
@Override
public void run() {
while(count > 0){
System.out.println("[" + this.getName() + "] count=" + count);
count --;
this.yield();//让出CPU
}
}
}
package com.gxx.threads.study.test11;
/**
* 测试类-测试线程yield()让出CPU
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
MyThread threadA = new MyThread();
threadA.setName("线程A");
threadA.start();
MyThread threadB = new MyThread();
threadB.setName("线程B");
threadB.start();
System.out.println("main 结束");
}
}
输出
main 开始
main 结束
[线程A] count=10
[线程B] count=10
[线程A] count=9
[线程B] count=9
[线程A] count=8
[线程B] count=8
[线程A] count=7
[线程B] count=7
[线程A] count=6
[线程B] count=6
[线程A] count=5
[线程B] count=5
[线程A] count=4
[线程B] count=4
[线程A] count=3
[线程B] count=3
[线程A] count=2
[线程B] count=2
[线程A] count=1
[线程B] count=1
==== 线程的优先级 ====
* 取值[1]~[10]的整数,默认值位[5]
* 设置优先级setPriority()
* 获取优先级getPriority()
package com.gxx.threads.study.test12;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 覆盖run方法
*/
@Override
public void run() {
System.out.println("run 开始");
System.out.println("线程[" + Thread.currentThread().getName() + "]优先级[继承][" + Thread.currentThread().getPriority() + "]");
System.out.println("run 结束");
}
}
package com.gxx.threads.study.test12;
/**
* 测试类-测试线程线程优先级的常量,默认值,范围和继承性
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("===线程优先级常量=开始======");
System.out.println("线程优先级MIN_PRIORITY=" + Thread.MIN_PRIORITY);
System.out.println("线程优先级NORM_PRIORITY=" + Thread.NORM_PRIORITY);
System.out.println("线程优先级MAX_PRIORITY=" + Thread.MAX_PRIORITY);
System.out.println("===线程优先级常量=结束======");
System.out.println("main 开始");
System.out.println("线程[" + Thread.currentThread().getName() + "]优先级[默认][" + Thread.currentThread().getPriority() + "]");
try{
System.out.println("=========");
System.out.println("线程[" + Thread.currentThread().getName() + "]优先级[设置][11]");
Thread.currentThread().setPriority(11);
} catch (Exception e){
System.out.println("设置[11]失败!");
System.out.println("线程优先级设置范围在[" + Thread.MIN_PRIORITY + "]~[" + Thread.MAX_PRIORITY + "]");
System.out.println("=========");
}
/**
* range MIN_PRIORITY to MAX_PRIORITY
* 设置线程优先级必须在[MIN_PRIORITY,MAX_PRIORITY]也就是[1,10]
*/
Thread.currentThread().setPriority(8);
System.out.println("线程[" + Thread.currentThread().getName() + "]优先级[设置][" + Thread.currentThread().getPriority() + "]");
MyThread thread = new MyThread();
thread.setName("线程A");
thread.start();
System.out.println("线程[" + Thread.currentThread().getName() + "]创建线程[" + thread.getName() + "]");
System.out.println("main 结束");
}
}
输出
===线程优先级常量=开始======
线程优先级MIN_PRIORITY=1
线程优先级NORM_PRIORITY=5
线程优先级MAX_PRIORITY=10
===线程优先级常量=结束======
main 开始
线程[main]优先级[默认][5]
=========
线程[main]优先级[设置][11]
设置[11]失败!
线程优先级设置范围在[1]~[10]
=========
线程[main]优先级[设置][8]
线程[main]创建线程[线程A]
main 结束
run 开始
线程[线程A]优先级[继承][8]
run 结束
* 优先级的规则性:优先级高的线程大部分先执行完
* 优先级的随机性:优先级高的线程不是所有都先执行完
* 优先级的速度:优先级高的线程运行速度快
package com.gxx.threads.study.test13;
import java.util.Date;
import java.util.Random;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 构造方法
* @param name 线程名字
* @param priority 优先级
*/
public MyThread(String name, int priority) {
this.setName(name);//设置线程名字
this.setPriority(priority);//设置优先级
}
/**
* 覆盖run方法
*/
@Override
public void run() {
long startTime = new Date().getTime();
for(int i=0; i<10000000; i++){
new Random().nextInt();
}
long endTime = new Date().getTime();
String name = "[高优先级]";
if(this.getPriority() <= 5){
name = "[低优先级]";
}
System.out.println(name + "线程[" + Thread.currentThread().getName() + "]运行结束,耗时[" + (endTime - startTime) + "]毫秒~");
}
}
package com.gxx.threads.study.test13;
/**
* 测试类-测试线程优先级的规则性,随机性,速度
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
MyThread thread1 = new MyThread("线程1", 10);
MyThread thread2 = new MyThread("线程2", 1);
MyThread thread3 = new MyThread("线程3", 10);
MyThread thread4 = new MyThread("线程4", 1);
MyThread thread5 = new MyThread("线程5", 10);
MyThread thread6 = new MyThread("线程6", 1);
MyThread thread7 = new MyThread("线程7", 10);
MyThread thread8 = new MyThread("线程8", 1);
MyThread thread9 = new MyThread("线程9", 10);
MyThread thread10 = new MyThread("线程10", 1);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
thread6.start();
thread7.start();
thread8.start();
thread9.start();
thread10.start();
System.out.println("main 结束");
}
}
输出
main 开始
main 结束
[高优先级]线程[线程1]运行结束,耗时[8021]毫秒~
[高优先级]线程[线程9]运行结束,耗时[8135]毫秒~
[低优先级]线程[线程6]运行结束,耗时[8168]毫秒~
[高优先级]线程[线程3]运行结束,耗时[8167]毫秒~
[低优先级]线程[线程2]运行结束,耗时[8167]毫秒~
[高优先级]线程[线程7]运行结束,耗时[8174]毫秒~
[低优先级]线程[线程10]运行结束,耗时[8185]毫秒~
[低优先级]线程[线程8]运行结束,耗时[8195]毫秒~
[低优先级]线程[线程4]运行结束,耗时[8198]毫秒~
[高优先级]线程[线程5]运行结束,耗时[8205]毫秒~
==== 守护线程 ====
守护线程比如垃圾回收器GC,当没有非守护线程的时候,守护线程没有意义,会自动停止!
package com.gxx.threads.study.test14;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 计数
*/
int count = 0;
/**
* 覆盖run方法
*/
@Override
public void run() {
while(true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + this.getName() + "][守护线程]打印count=" + (++count));
}
}
}
package com.gxx.threads.study.test14;
/**
* 测试类-测试守护线程
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("[main][非守护线程] 开始");
MyThread thread = new MyThread();
thread.setName("Thead");
System.out.println("[线程][" + thread.getName() + "]默认为" + (thread.isDaemon()?"[true][守护线程]":"[false][非守护线程]"));
System.out.println("[线程][" + thread.getName() + "]设置为[true][守护线程]");
thread.setDaemon(true);
thread.start();
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[main][非守护线程] 结束,则[守护线程]也自动结束");
}
}
输出
[main][非守护线程] 开始
[线程][Thead]默认为[false][非守护线程]
[线程][Thead]设置为[true][守护线程]
[Thead][守护线程]打印count=1
[Thead][守护线程]打印count=2
[Thead][守护线程]打印count=3
[Thead][守护线程]打印count=4
[Thead][守护线程]打印count=5
[Thead][守护线程]打印count=6
[Thead][守护线程]打印count=7
[Thead][守护线程]打印count=8
[Thead][守护线程]打印count=9
[main][非守护线程] 结束,则[守护线程]也自动结束
===== 对象及变量的并发访问 =====
==== synchronized同步方法 ====
=== 方法内变量为线程安全 ===
package com.gxx.threads.study.test15;
/**
* 数字处理器
* @author Gxx
*/
public class NumProcess {
/**
* 处理逻辑
*/
public void process(){
System.out.println("[" + Thread.currentThread().getName() + "]进入process~");
/**
* 方法内变量
*/
int num;
/**
* 根据线程名称走不同分支
*/
if(Thread.currentThread().getName().equals("线程A")){
num = 100;
try {
Thread.sleep(2000);//睡眠2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
num = 200;
}
System.out.println("[" + Thread.currentThread().getName() + "] num=" + num);
}
}
package com.gxx.threads.study.test15;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 数字处理器
*/
NumProcess numProcess;
/**
* 构造方法
* @param name
* @param numProcess
*/
public MyThread(String name, NumProcess numProcess) {
this.setName(name);
this.numProcess = numProcess;
}
/**
* 覆盖run方法
*/
@Override
public void run() {
numProcess.process();
}
}
package com.gxx.threads.study.test15;
/**
* 测试类-测试方法内变量并发访问
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
NumProcess numProcess = new NumProcess();
MyThread threadA = new MyThread("线程A", numProcess);
MyThread threadB = new MyThread("线程B", numProcess);
threadA.start();
threadB.start();
System.out.println("main 结束");
}
}
输出
main 开始
main 结束
[线程A]进入process~
[线程B]进入process~
[线程B] num=200
[线程A] num=100
=== 实例变量非线程安全 ===
package com.gxx.threads.study.test16;
/**
* 数字处理器
* @author Gxx
*/
public class NumProcess {
/**
* 实例变量
*/
int num;
/**
* 处理逻辑
*/
public void process(){
System.out.println("[" + Thread.currentThread().getName() + "]进入process~");
/**
* 根据线程名称走不同分支
*/
if(Thread.currentThread().getName().equals("线程A")){
num = 100;
try {
Thread.sleep(2000);//睡眠2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
num = 200;
}
System.out.println("[" + Thread.currentThread().getName() + "] num=" + num);
}
}
package com.gxx.threads.study.test16;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 数字处理器
*/
NumProcess numProcess;
/**
* 构造方法
* @param name
* @param numProcess
*/
public MyThread(String name, NumProcess numProcess) {
this.setName(name);
this.numProcess = numProcess;
}
/**
* 覆盖run方法
*/
@Override
public void run() {
numProcess.process();
}
}
package com.gxx.threads.study.test16;
/**
* 测试类-测试实例变量并发访问
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
NumProcess numProcess = new NumProcess();
MyThread threadA = new MyThread("线程A", numProcess);
MyThread threadB = new MyThread("线程B", numProcess);
threadA.start();
threadB.start();
System.out.println("main 结束");
}
}
输出
main 开始
main 结束
[线程A]进入process~
[线程B]进入process~
[线程B] num=200
[线程A] num=200
=== 实例变量非线程安全,synchronized同步 ===
package com.gxx.threads.study.test17;
/**
* 数字处理器
* @author Gxx
*/
public class NumProcess {
/**
* 实例变量
*/
int num;
/**
* 处理逻辑
*/
public synchronized void process(){
System.out.println("[" + Thread.currentThread().getName() + "]进入process~");
/**
* 根据线程名称走不同分支
*/
if(Thread.currentThread().getName().equals("线程A")){
num = 100;
try {
Thread.sleep(2000);//睡眠2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
num = 200;
}
System.out.println("[" + Thread.currentThread().getName() + "] num=" + num);
}
}
package com.gxx.threads.study.test17;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 数字处理器
*/
NumProcess numProcess;
/**
* 构造方法
* @param name
* @param numProcess
*/
public MyThread(String name, NumProcess numProcess) {
this.setName(name);
this.numProcess = numProcess;
}
/**
* 覆盖run方法
*/
@Override
public void run() {
numProcess.process();
}
}
package com.gxx.threads.study.test17;
/**
* 测试类-测试实例变量并发访问,synchronized同步
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
NumProcess numProcess = new NumProcess();
MyThread threadA = new MyThread("线程A", numProcess);
MyThread threadB = new MyThread("线程B", numProcess);
threadA.start();
threadB.start();
System.out.println("main 结束");
}
}
输出
main 开始
main 结束
[线程A]进入process~
[线程A] num=100
[线程B]进入process~
[线程B] num=200
=== 多个对象多个锁 ===
package com.gxx.threads.study.test18;
/**
* 数字处理器
* @author Gxx
*/
public class NumProcess {
/**
* 实例变量
*/
int num;
/**
* 处理逻辑
*/
public synchronized void process(){
System.out.println("[" + Thread.currentThread().getName() + "]进入process~");
/**
* 根据线程名称走不同分支
*/
if(Thread.currentThread().getName().equals("线程A")){
num = 100;
try {
Thread.sleep(2000);//睡眠2秒
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
num = 200;
}
System.out.println("[" + Thread.currentThread().getName() + "] num=" + num);
}
}
package com.gxx.threads.study.test18;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 数字处理器
*/
NumProcess numProcess;
/**
* 构造方法
* @param name
* @param numProcess
*/
public MyThread(String name, NumProcess numProcess) {
this.setName(name);
this.numProcess = numProcess;
}
/**
* 覆盖run方法
*/
@Override
public void run() {
numProcess.process();
}
}
package com.gxx.threads.study.test18;
/**
* 测试类-测试多个对象多个锁
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
NumProcess numProcess1 = new NumProcess();
MyThread threadA = new MyThread("线程A", numProcess1);
NumProcess numProcess2 = new NumProcess();
MyThread threadB = new MyThread("线程B", numProcess2);
threadA.start();
threadB.start();
System.out.println("main 结束");
}
}
输出
main 开始
main 结束
[线程A]进入process~
[线程B]进入process~
[线程B] num=200
[线程A] num=100
=== synchronized方法与锁对象 ===
* 线程进synchronized方法获取锁,都是锁对象实例,其他线程可以进该实例其他不带synchronized的方法
package com.gxx.threads.study.test19;
/**
* 方法处理器
* @author Gxx
*/
public class MethodProcess {
/**
* 方法A
*/
public synchronized void methodA(){
System.out.println("[" + Thread.currentThread().getName() + "]进入methodA~");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + Thread.currentThread().getName() + "]methodA结束");
}
/**
* 方法B
*/
public void methodB(){
System.out.println("[" + Thread.currentThread().getName() + "]进入methodB~");
System.out.println("[" + Thread.currentThread().getName() + "]methodB结束");
}
}
package com.gxx.threads.study.test19;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 方法处理器
*/
MethodProcess methodProcess;
/**
* 构造方法
* @param name
* @param methodProcess
*/
public MyThread(String name, MethodProcess methodProcess) {
this.setName(name);
this.methodProcess = methodProcess;
}
/**
* 覆盖run方法
*/
@Override
public void run() {
if("线程A".equals(this.getName())){
methodProcess.methodA();
} else {
methodProcess.methodB();
}
}
}
package com.gxx.threads.study.test19;
/**
* 测试类-测试synchronized方法与锁对象
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
MethodProcess methodProcess = new MethodProcess();
MyThread threadA = new MyThread("线程A", methodProcess);
MyThread threadB = new MyThread("线程B", methodProcess);
threadA.start();
threadB.start();
System.out.println("main 结束");
}
}
输出
main 开始
main 结束
[线程A]进入methodA~
[线程B]进入methodB~
[线程B]methodB结束
[线程A]methodA结束
* 线程A进synchronized的方法A,获取了锁,同时,线程B想进synchronized的方法B,得排队
package com.gxx.threads.study.test20;
/**
* 方法处理器
* @author Gxx
*/
public class MethodProcess {
/**
* 方法A
*/
public synchronized void methodA(){
System.out.println("[" + Thread.currentThread().getName() + "]进入methodA~");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + Thread.currentThread().getName() + "]methodA结束");
}
/**
* 方法B
*/
public synchronized void methodB(){
System.out.println("[" + Thread.currentThread().getName() + "]进入methodB~");
System.out.println("[" + Thread.currentThread().getName() + "]methodB结束");
}
}
package com.gxx.threads.study.test20;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 方法处理器
*/
MethodProcess methodProcess;
/**
* 构造方法
* @param name
* @param methodProcess
*/
public MyThread(String name, MethodProcess methodProcess) {
this.setName(name);
this.methodProcess = methodProcess;
}
/**
* 覆盖run方法
*/
@Override
public void run() {
if("线程A".equals(this.getName())){
methodProcess.methodA();
} else {
methodProcess.methodB();
}
}
}
package com.gxx.threads.study.test20;
/**
* 测试类-测试synchronized方法与锁对象
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
MethodProcess methodProcess = new MethodProcess();
MyThread threadA = new MyThread("线程A", methodProcess);
MyThread threadB = new MyThread("线程B", methodProcess);
threadA.start();
threadB.start();
System.out.println("main 结束");
}
}
输出
main 开始
main 结束
[线程A]进入methodA~
[线程A]methodA结束
[线程B]进入methodB~
[线程B]methodB结束
=== synchronized锁重入与异常释放锁 ===
* 当前类中不同synchronized方法可以锁重入
* 父子类中不同synchronized方法可以锁重入
* 发生异常,立刻释放锁
package com.gxx.threads.study.test21;
/**
* 方法处理器
* @author Gxx
*/
public class MethodProcess extends MethodProcessParent {
/**
* 方法A
*/
public synchronized void methodA(){
System.out.println("[" + Thread.currentThread().getName() + "]进入methodA~");
methodB();
}
/**
* 方法B
*/
public synchronized void methodB(){
System.out.println("[" + Thread.currentThread().getName() + "]进入methodB~");
methodC();
}
/**
* 方法C
*/
public synchronized void methodC(){
System.out.println("[" + Thread.currentThread().getName() + "]进入methodC~");
super.methodD();
}
}
package com.gxx.threads.study.test21;
/**
* 方法处理器
* @author Gxx
*/
public class MethodProcessParent {
/**
* 计数
*/
int count = 0;
/**
* 方法D
*/
public synchronized void methodD(){
System.out.println("[" + Thread.currentThread().getName() + "]进入methodD~");
while (true) {
System.out.println("[" + Thread.currentThread().getName() + "]打印count=" + count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(++count == 5){
count = 0;
throw new RuntimeException("手动抛出异常~");
}
}
}
}
package com.gxx.threads.study.test21;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 方法处理器
*/
MethodProcess methodProcess;
/**
* 构造方法
* @param name
* @param methodProcess
*/
public MyThread(String name, MethodProcess methodProcess) {
this.setName(name);
this.methodProcess = methodProcess;
}
/**
* 覆盖run方法
*/
@Override
public void run() {
methodProcess.methodA();
}
}
package com.gxx.threads.study.test21;
/**
* 测试类-测试synchronized锁重入
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
MethodProcess methodProcess = new MethodProcess();
MyThread threadA = new MyThread("线程A", methodProcess);
threadA.start();
MyThread threadB = new MyThread("线程B", methodProcess);
threadB.start();
System.out.println("main 结束");
}
}
输出
main 开始
main 结束
[线程A]进入methodA~
[线程A]进入methodB~
[线程A]进入methodC~
[线程A]进入methodD~
[线程A]打印count=0
[线程A]打印count=1
[线程A]打印count=2
[线程A]打印count=3
[线程A]打印count=4
[线程B]进入methodA~
Exception in thread "线程A" java.lang.RuntimeException: 手动抛出异常~
at com.gxx.threads.study.test21.MethodProcessParent.methodD(MethodProcessParent.java:27)
at com.gxx.threads.study.test21.MethodProcess.methodC(MethodProcess.java:29)
at com.gxx.threads.study.test21.MethodProcess.methodB(MethodProcess.java:21)
at com.gxx.threads.study.test21.MethodProcess.methodA(MethodProcess.java:13)
at com.gxx.threads.study.test21.MyThread.run(MyThread.java:28)
[线程B]进入methodB~
[线程B]进入methodC~
[线程B]进入methodD~
[线程B]打印count=0
[线程B]打印count=1
[线程B]打印count=2
[线程B]打印count=3
[线程B]打印count=4
Exception in thread "线程B" java.lang.RuntimeException: 手动抛出异常~
at com.gxx.threads.study.test21.MethodProcessParent.methodD(MethodProcessParent.java:27)
at com.gxx.threads.study.test21.MethodProcess.methodC(MethodProcess.java:29)
at com.gxx.threads.study.test21.MethodProcess.methodB(MethodProcess.java:21)
at com.gxx.threads.study.test21.MethodProcess.methodA(MethodProcess.java:13)
at com.gxx.threads.study.test21.MyThread.run(MyThread.java:28)
=== 同步不具有继承性 ===
package com.gxx.threads.study.test22;
/**
* 方法处理器
* @author Gxx
*/
public class MethodProcess extends MethodProcessParent {
/**
* 处理
*/
public void process(){
System.out.println("[" + Thread.currentThread().getName() + "]进入process~");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + Thread.currentThread().getName() + "]process结束");
}
}
package com.gxx.threads.study.test22;
/**
* 方法处理器
* @author Gxx
*/
public class MethodProcessParent {
/**
* 处理
*/
public synchronized void process(){
System.out.println("[" + Thread.currentThread().getName() + "]进入process~");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("[" + Thread.currentThread().getName() + "]process结束");
}
}
package com.gxx.threads.study.test22;
/**
* 自定义线程类
* @author Gxx
*/
public class MyThread extends Thread {
/**
* 方法处理器
*/
MethodProcess methodProcess;
/**
* 构造方法
* @param name
* @param methodProcess
*/
public MyThread(String name, MethodProcess methodProcess) {
this.setName(name);
this.methodProcess = methodProcess;
}
/**
* 覆盖run方法
*/
@Override
public void run() {
methodProcess.process();
}
}
package com.gxx.threads.study.test22;
/**
* 测试类-测试同步不具有继承性
* @author Gxx
*/
public class Test {
/**
* main方法
* @param args
*/
public static void main(String[] args) {
System.out.println("main 开始");
MethodProcess methodProcess = new MethodProcess();
MyThread threadA = new MyThread("线程A", methodProcess);
MyThread threadB = new MyThread("线程B", methodProcess);
threadA.start();
threadB.start();
System.out.println("main 结束");
}
}
输出
main 开始
main 结束
[线程B]进入process~
[线程A]进入process~
[线程B]process结束
[线程A]process结束