用户工具

站点工具


分享:技术:多线程:多线程编程核心技术整理

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
分享:技术:多线程:多线程编程核心技术整理 [2016/05/29 10:34]
gxx
分享:技术:多线程:多线程编程核心技术整理 [2016/06/19 18:16] (当前版本)
gxx
行 91: 行 91:
  */  */
 public class MyThread extends Thread { public class MyThread extends Thread {
 + /**
 + * 构造方法
 + */
 + public MyThread(){
 + System.out.println("​线程["​ + Thread.currentThread().getName() + "​]执行构造方法"​);​
 + }
 +
  /**  /**
  * 覆盖run方法  * 覆盖run方法
行 96: 行 103:
  @Override  @Override
  public void run() {  public void run() {
- System.out.println("​线程["​ + Thread.currentThread().getName() + "​]执行"​);​+ System.out.println("​线程["​ + Thread.currentThread().getName() + "​]执行run");
  }  }
 } }
行 114: 行 121:
  public static void main(String[] args) {  public static void main(String[] args) {
  MyThread thread = new MyThread();  MyThread thread = new MyThread();
 + thread.setName("​线程A"​);//​设置线程名字
  thread.run();​  thread.run();​
  thread.start();​  thread.start();​
行 122: 行 130:
 输出 输出
 <​code>​ <​code>​
-线程[main]执行 +线程[main]执行构造方法 
-线程[Thread-0]执行+线程[main]执行run 
 +线程[线程A]执行run
 Exception in thread "​main"​ java.lang.IllegalThreadStateException Exception in thread "​main"​ java.lang.IllegalThreadStateException
  at java.lang.Thread.start(Thread.java:​705)  at java.lang.Thread.start(Thread.java:​705)
- at com.gxx.threads.study.test3.Test.main(Test.java:​16)+ at com.gxx.threads.study.test3.Test.main(Test.java:​17)
 </​code>​ </​code>​
 === 不共享变量,线程安全 === === 不共享变量,线程安全 ===
 <code java MyThread.java>​ <code java MyThread.java>​
-package com.gxx.threads.study.test3;+package com.gxx.threads.study.test4;
  
 /**  /** 
行 152: 行 161:
 </​code>​ </​code>​
 <code java TestSafe.java>​ <code java TestSafe.java>​
-package com.gxx.threads.study.test3;+package com.gxx.threads.study.test4;
  
 /** /**
行 202: 行 211:
 === 共享变量,线程不安全 === === 共享变量,线程不安全 ===
 <code java TestNotSafe.java>​ <code java TestNotSafe.java>​
-package com.gxx.threads.study.test3;+package com.gxx.threads.study.test4;
  
 /** /**
行 253: 行 262:
 === 共享变量,使用synchronized使得线程安全 === === 共享变量,使用synchronized使得线程安全 ===
 <code java Tools.java>​ <code java Tools.java>​
-package com.gxx.threads.study.test4;+package com.gxx.threads.study.test5;
  
 /**  /** 
行 284: 行 293:
 </​code>​ </​code>​
 <code java MyThread.java>​ <code java MyThread.java>​
-package com.gxx.threads.study.test4;+package com.gxx.threads.study.test5;
  
 /**  /** 
行 314: 行 323:
 </​code>​ </​code>​
 <code java Test.java>​ <code java Test.java>​
-package com.gxx.threads.study.test4;+package com.gxx.threads.study.test5;
  
 /** /**
行 341: 行 350:
 线程[Thread-0]执行count=9 线程[Thread-0]执行count=9
 线程[Thread-1]执行count=8 线程[Thread-1]执行count=8
 +</​code>​
 +=== count--和System.out.println() ===
 +注意:
 +  * count--不是同步的,分三步1.获取count的值;2.count-1;3.再赋值给count;不同步则有时间差
 +  * System.out.println()是同步的
 +<code java println.java>​
 +public void println(String x) {
 +    synchronized (this) {
 +        print(x);
 +        newLine();
 +    }
 +}
 +</​code>​
 +==== getId()、isAlive()和sleep() ====
 +  * getId 是取得线程的唯一标识
 +  * isAlive是判断当前线程是否处于活动状态
 +  * sleep是指this.currentThread()休眠多少毫秒
 +<code java MyThread.java>​
 +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());​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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();​
 + }
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +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
 +</​code>​
 +==== 停止线程 ====
 +=== interrupt、isInterrupted、interrupted ===
 +  * interrupt
 +给线程打个中断的标记,线程继续运行
 +  * isInterrupted
 +判断线程是否有中断的标记,如果有返回true,多次调用都返回true
 +  * interrupted
 +静态方法,Thread.interrupted(),判断当前线程是否有中断的标记,如果有返回true,并清空该标记,下次再执行,则返回false
 +<code java MyThread.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +main 开始
 +main 结束
 +run 开始
 +执行this.interrupt()只是打个线程中断标记,线程还是继续往下走
 +this.isInterrupted()=true
 +this.isInterrupted()=true
 +执行静态方法Thread.interrupted()=true后清空中断状态
 +再执行静态方法Thread.interrupted()=false
 +this.isInterrupted()=false
 +run 结束
 +</​code>​
 +=== 测试线程interrupt()然后sleep() ===
 +先中断,再睡眠,会抛出异常
 +<code java MyThread.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +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)
 +
 +</​code>​
 +=== 测试线程sleep()然后interrupt() ===
 +在睡眠的过程中,中断,会抛出异常
 +<code java MyThread.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +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)
 +</​code>​
 +=== 抛出异常或者return来停止线程 ===
 +建议使用这两种方式
 +<code java>
 +if(this.isInterrupted()){
 + throw new Exception();​
 +}
 +</​code>​
 +<code java>
 +if(this.interrupted()){
 + return;
 +}
 +</​code>​
 +=== stop()暴力停止,@Deprecated作废 ===
 +不建议使用,因为stop()停止线程有可能使一些清理性的工作得不到完成。另外会对锁定的对象强制解锁,导致数据得不到同步的处理,出现数据不一致的问题!比如:
 +<code java>
 +synchronized public void setUserNameAndPassword(String userName, String password){
 + this.userName = userName;
 + Thread.sleep(1000000);//​正好外面执行stop(),导致数据不一致
 + this.password = password;
 +}
 +</​code>​
 +==== suspend()和resume() ====
 +  * suspend()暂停
 +如果synchronized方法执行一半,不会释放锁,一直卡着,比如线程内System.out.println()打印一半(打印数据,再打印换行,有synchronized代码块)暂停了,其他地方调System.out.println()都会一直卡着,输出不到控台;@Deprecated作废,不建议使用
 +  * resume()恢复
 +从暂停的地方恢复,程序往下走,但是有时间差,可能会有脏数据;@Deprecated作废,不建议使用
 +<code java MyThread.java>​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 结束"​);​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +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 结束
 +</​code>​
 +==== yield() ====
 +让出CPU资源,但是有可能让出又马上获得CPU时间片。
 +<code java MyThread.java>​
 +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
 + }
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +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
 +</​code>​
 +==== 线程的优先级 ====
 +  * 取值[1]~[10]的整数,默认值位[5]
 +  * 设置优先级setPriority()
 +  * 获取优先级getPriority()
 +<code java MyThread.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +===线程优先级常量=开始======
 +线程优先级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 结束
 +</​code>​
 +  * 优先级的规则性:优先级高的线程大部分先执行完
 +  * 优先级的随机性:优先级高的线程不是所有都先执行完
 +  * 优先级的速度:优先级高的线程运行速度快
 +<code java MyThread.java>​
 +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) + "​]毫秒~"​);​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +main 开始
 +main 结束
 +[高优先级]线程[线程1]运行结束,耗时[8021]毫秒~
 +[高优先级]线程[线程9]运行结束,耗时[8135]毫秒~
 +[低优先级]线程[线程6]运行结束,耗时[8168]毫秒~
 +[高优先级]线程[线程3]运行结束,耗时[8167]毫秒~
 +[低优先级]线程[线程2]运行结束,耗时[8167]毫秒~
 +[高优先级]线程[线程7]运行结束,耗时[8174]毫秒~
 +[低优先级]线程[线程10]运行结束,耗时[8185]毫秒~
 +[低优先级]线程[线程8]运行结束,耗时[8195]毫秒~
 +[低优先级]线程[线程4]运行结束,耗时[8198]毫秒~
 +[高优先级]线程[线程5]运行结束,耗时[8205]毫秒~
 +</​code>​
 +==== 守护线程 ====
 +守护线程比如垃圾回收器GC,当没有非守护线程的时候,守护线程没有意义,会自动停止!
 +<code java MyThread.java>​
 +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));
 + }
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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][非守护线程] 结束,则[守护线程]也自动结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +[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][非守护线程] 结束,则[守护线程]也自动结束
 +</​code>​
 +===== 对象及变量的并发访问 =====
 +==== synchronized同步方法 ====
 +=== 方法内变量为线程安全 ===
 +<code java NumProcess.java>​
 +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);
 + }
 +}
 +</​code>​
 +<code java MyThead.java>​
 +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();​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +main 开始
 +main 结束
 +[线程A]进入process~
 +[线程B]进入process~
 +[线程B] num=200
 +[线程A] num=100
 +</​code>​
 +=== 实例变量非线程安全 ===
 +<code java NumProcess.java>​
 +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);
 + }
 +}
 +</​code>​
 +<code java MyThead.java>​
 +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();​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +main 开始
 +main 结束
 +[线程A]进入process~
 +[线程B]进入process~
 +[线程B] num=200
 +[线程A] num=200
 +</​code>​
 +=== 实例变量非线程安全,synchronized同步 ===
 +<code java NumProcess.java>​
 +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);
 + }
 +}
 +</​code>​
 +<code java MyThead.java>​
 +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();​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +main 开始
 +main 结束
 +[线程A]进入process~
 +[线程A] num=100
 +[线程B]进入process~
 +[线程B] num=200
 +</​code>​
 +=== 多个对象多个锁 ===
 +<code java NumProcess.java>​
 +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);
 + }
 +}
 +</​code>​
 +<code java MyThead.java>​
 +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();​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +main 开始
 +main 结束
 +[线程A]进入process~
 +[线程B]进入process~
 +[线程B] num=200
 +[线程A] num=100
 +</​code>​
 +=== synchronized方法与锁对象 ===
 +  * 线程进synchronized方法获取锁,都是锁对象实例,其他线程可以进该实例其他不带synchronized的方法
 +<code java MethodProcess.java>​
 +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结束"​);​
 + }
 +}
 +</​code>​
 +<code java MyThead.java>​
 +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();​
 + }
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +main 开始
 +main 结束
 +[线程A]进入methodA~
 +[线程B]进入methodB~
 +[线程B]methodB结束
 +[线程A]methodA结束
 +</​code>​
 +  * 线程A进synchronized的方法A,获取了锁,同时,线程B想进synchronized的方法B,得排队
 +<code java MethodProcess.java>​
 +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结束"​);​
 + }
 +}
 +</​code>​
 +<code java MyThead.java>​
 +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();​
 + }
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +main 开始
 +main 结束
 +[线程A]进入methodA~
 +[线程A]methodA结束
 +[线程B]进入methodB~
 +[线程B]methodB结束
 +</​code>​
 +=== synchronized锁重入与异常释放锁 ===
 +  * 当前类中不同synchronized方法可以锁重入
 +  * 父子类中不同synchronized方法可以锁重入
 +  * 发生异常,立刻释放锁
 +<code java MethodProcess.java>​
 +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();​
 + }
 +}
 +</​code>​
 +<code java MethodProcessParent.java>​
 +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("​手动抛出异常~"​);​
 + }
 + }
 + }
 +}
 +</​code>​
 +<code java MyThead.java>​
 +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();​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +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)
 +</​code>​
 +=== 同步不具有继承性 ===
 +<code java MethodProcess.java>​
 +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结束"​);​
 + }
 +}
 +</​code>​
 +<code java MethodProcessParent.java>​
 +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结束"​);​
 + }
 +}
 +</​code>​
 +<code java MyThead.java>​
 +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();​
 + }
 +}
 +</​code>​
 +<code java Test.java>​
 +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 结束"​);​
 + }
 +}
 +</​code>​
 +输出
 +<​code>​
 +main 开始
 +main 结束
 +[线程B]进入process~
 +[线程A]进入process~
 +[线程B]process结束
 +[线程A]process结束
 </​code>​ </​code>​
分享/技术/多线程/多线程编程核心技术整理.1464489263.txt.gz · 最后更改: 2016/05/29 10:34 由 gxx