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
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()"); } }
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(),CPU在不确定的时间调用run()
直接执行run,就不是“线程规划器”来调度了,而是执行run()的当前线程直接调用方法,如果是main()中调用,则当前线程就是main
多次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
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
注意:
public void println(String x) { synchronized (this) { print(x); newLine(); } }
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
给线程打个中断的标记,线程继续运行
判断线程是否有中断的标记,如果有返回true,多次调用都返回true
静态方法,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 结束
先中断,再睡眠,会抛出异常
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)
在睡眠的过程中,中断,会抛出异常
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)
不建议使用,因为stop()停止线程有可能使一些清理性的工作得不到完成。另外会对锁定的对象强制解锁,导致数据得不到同步的处理,出现数据不一致的问题!比如:
synchronized public void setUserNameAndPassword(String userName, String password){ this.userName = userName; Thread.sleep(1000000);//正好外面执行stop(),导致数据不一致 this.password = password; }
如果synchronized方法执行一半,不会释放锁,一直卡着,比如线程内System.out.println()打印一半(打印数据,再打印换行,有synchronized代码块)暂停了,其他地方调System.out.println()都会一直卡着,输出不到控台;@Deprecated作废,不建议使用
从暂停的地方恢复,程序往下走,但是有时间差,可能会有脏数据;@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 结束
让出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
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][非守护线程] 结束,则[守护线程]也自动结束
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
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
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结束
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结束
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结束