标签:java线程同步 关键字synchronized 同步方法和同步块 wait方法和notify方法 noti 线程调度
实例: package thread.synchronize; /** * 创建Computer类 * 其中包含同步方法,非同步方法和含有同步块的非同步方法 * @author 学霸联盟 - 赵灿 */ public class Computer { /** * 非同步方法;功能:听音乐 * @param threadTag:线程标记,用于标识哪个线程正在执行这个方法 */ public void listenMusic(String threadTag) { System.out.println(threadTag + "-听音乐开始"); try { //此处休眠1秒是为了模拟编写代码消耗的时间 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadTag + "-听音乐结束"); } /** * 含有同步块的非同步方法;功能:打印材料 * @param threadTag:线程标记,用于标识哪个线程正在执行这个方法 */ public void printer(String threadTag) { System.out.println(threadTag + "-准备材料开始"); try { //此处休眠1秒是为了模拟准备材料消耗的时间 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadTag + "-准备材料结束"); //同步块:获得当前对象的锁 synchronized(this){ System.out.println(threadTag + "-打印材料开始"); try { //此处休眠1秒是为了模拟打印材料消耗的时间 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadTag + "-打印材料结束"); } } /** * 同步方法;功能:玩游戏 * @param threadTag:线程标记,用于标识哪个线程正在执行这个方法 */ public synchronized void playGame(String threadTag) { System.out.println(threadTag + "-玩游戏开始"); try { //此处休眠3秒是为了模拟玩游戏消耗的时间 Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadTag + "-玩游戏结束"); } /** * 同步方法;功能:编写代码 * @param threadTag:线程标记,用于标识哪个线程正在执行这个方法 */ public synchronized void coding(String threadTag) { System.out.println(threadTag + "-编写代码开始"); try { //此处休眠3秒是为了模拟编写代码消耗的时间 Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(threadTag + "-编写代码结束"); } } package thread.synchronize; /** * 创建ThreadA类 * 用于执行Computer对象中的非同步方法listenMusic * @author 学霸联盟 - 赵灿 */ public class ThreadA extends Thread { /* * 声明成员变量pc * 目的是因为在run方法中需要使用外部传进来的Computer对象 * 但run方法中无法使用构造方法中的局部变量localPC * 所以此处声明一个成员变量pc用于接收外部传入的对象 * 这样以来run方法中,便可以通过成员变量pc可以使用外部传入的对象了 */ private Computer pc; /* * 此处的localPC会接收到外部传入的Computer类型的对象 * 并将其传递给成员变量pc */ public ThreadA(Computer localPC) { pc = localPC; } @Override public void run() { //使用pc完成听音乐的更能,即使用pc调用listenMusic方法 pc.listenMusic("ThreadA"); } } package thread.synchronize; /** * 创建ThreadB类:作用和代码同ThreadA * @author 学霸联盟 - 赵灿 */ public class ThreadB extends Thread { private Computer pc; public ThreadB(Computer localPC) { pc = localPC; } @Override public void run() { pc.listenMusic("ThreadB"); } } package thread.synchronize; /** * 创建测试类TestAB * 用于测试多个线程同时调用同一对象的同一个非同步方法 * 结果将是多个线程同时执行非同步方法 * @author 学霸联盟 - 赵灿 */ public class TestAB { public static void main(String[] args) { /** * 为了保证只有一台电脑(即同一个对象)供多个线程访问 * 所以只在此处创建一个Computer对象作为实参传递给各个线程 */ Computer pc = new Computer(); //ThreadA和ThreadB中都执行了pc的非同步方法listenMusic ThreadA ta = new ThreadA(pc); ThreadB tb = new ThreadB(pc); //启动线程ta和tb ta.start(); tb.start(); } } 运行结果: ThreadA-听音乐开始 ThreadB-听音乐开始 ThreadB-听音乐结束 ThreadA-听音乐结束
package thread.synchronize; /** * 创建ThreadC类:代码基本和ThreadA相同 * @author 学霸联盟 - 赵灿 */ public class ThreadC extends Thread { private Computer pc; public ThreadC(Computer localPC) { pc = localPC; } @Override public void run() { //调用pc的同步方法playGame pc.playGame("ThreadC"); } } package thread.synchronize; /** * 创建测试类TestBC * 用于测试两个线程同时调用同一对象的非同步方法和同步方法 * 结果是执行非同步方法和同步方法的两个线程可以同时执行,互不影响 * @author 学霸联盟 - 赵灿 */ public class TestBC { public static void main(String[] args) { /** * 为了保证只有一台电脑(即同一个对象)供多个线程访问 * 所以只在此处创建一个Computer对象作为实参传递给各个线程 */ Computer pc = new Computer(); //ThreadB执行了pc的非同步方法listenMusic ThreadB tb = new ThreadB(pc); //ThreadC执行了pc的同步方法playGame ThreadC tc = new ThreadC(pc); tb.start(); tc.start(); } } 运行结果: ThreadC-玩游戏开始 ThreadB-听音乐开始 ThreadB-听音乐结束 ThreadC-玩游戏结束
package thread.synchronize; /** * 创建ThreadD类:代码和功能同ThreadC * @author 学霸联盟 - 赵灿 */ public class ThreadD extends Thread { private Computer pc; public ThreadD(Computer localPC) { pc = localPC; } @Override public void run() { //调用pc的同步方法playGame pc.playGame("ThreadD"); } } package thread.synchronize; /** * 创建测试类TestCD * 用于测试多个线程同时调用同一对象的同一个同步方法 * 结果是某一线程先获得对象的锁的执行完后,第二个线程才能执行 * @author 学霸联盟 - 赵灿 */ public class TestCD { public static void main(String[] args) { /** * 为了保证只有一台电脑(即同一个对象)供多个线程访问 * 所以只在此处创建一个Computer对象作为实参传递给各个线程 */ Computer pc = new Computer(); //ThreadC和ThreadD中都执行了pc的同步方法playGame ThreadC tc = new ThreadC(pc); ThreadD td = new ThreadD(pc); //启动线程tc和td tc.start(); td.start(); } } 运行结果: ThreadC-玩游戏开始 ThreadC-玩游戏结束 ThreadD-玩游戏开始 ThreadD-玩游戏结束
package thread.synchronize; /** * 创建ThreadE类 * @author 学霸联盟 - 赵灿 */ public class ThreadE extends Thread { private Computer pc; public ThreadE(Computer localPC) { pc = localPC; } @Override public void run() { //调用pc的同步方法coding pc.coding("ThreadE"); } } package thread.synchronize; /** * 创建测试类TestDE * 用于测试多个线程同时调用同一对象的不同的同步方法 * 结果也是某一线程先获得对象的锁的执行完后,第二个线程才能执行 * @author 学霸联盟 - 赵灿 */ public class TestDE { public static void main(String[] args) { /** * 为了保证只有一台电脑(即同一个对象)供多个线程访问 * 所以只在此处创建一个Computer对象作为实参传递给各个线程 */ Computer pc = new Computer(); //ThreadD执行了pc的同步方法playGame ThreadD td = new ThreadD(pc); //ThreadE中执行了pc的同步方法coding ThreadE te = new ThreadE(pc); td.start(); te.start(); } } 运行结果: ThreadD-玩游戏开始 ThreadD-玩游戏结束 ThreadE-编写代码开始 ThreadE-编写代码结束
package thread.synchronize; /** * 创建ThreadF类 * @author 学霸联盟 - 赵灿 */ public class ThreadF extends Thread { private Computer pc; public ThreadF(Computer localPC) { pc = localPC; } @Override public void run() { //调用pc的含同步块的方法printer pc.printer("ThreadF"); } } package thread.synchronize; /** * 创建测试类TestEF * 用于测试多个线程同时调用同一对象的同步方法和含有同步块的非同步方法 * 结果将是被同步的部分有先后,非同步部分代码同时执行 * @author 学霸联盟 - 赵灿 */ public class TestEF { public static void main(String[] args) { /** * 为了保证只有一台电脑(即同一个对象)供多个线程访问 * 所以只在此处创建一个Computer对象作为实参传递给各个线程 */ Computer pc = new Computer(); //ThreadE中执行了pc的同步方法coding ThreadE te = new ThreadE(pc); //ThreadF执行了pc的含同步块的非同步方法printer ThreadF tf = new ThreadF(pc); te.start(); tf.start(); } } 运行结果: ThreadF-准备材料开始 ThreadE-编写代码开始 ThreadF-准备材料结束 ThreadE-编写代码结束 ThreadF-打印材料开始 ThreadF-打印材料结束
package thread.synchronize; /** * 创建ThreadG类 * @author 学霸联盟 - 赵灿 */ public class ThreadG extends Thread { private Computer pc; public ThreadG(Computer localPC) { pc = localPC; } @Override public void run() { //调用pc的含同步块的方法printer pc.printer("ThreadG"); } } package thread.synchronize; /** * 创建测试类TestFG * 用于测试多个线程同时调用同一对象中同一个含有同步块的非同步方法 * 结果将是被同步的部分有先后,非同步部分代码同时执行 * @author 学霸联盟 - 赵灿 */ public class TestFG { public static void main(String[] args) { /** * 为了保证只有一台电脑(即同一个对象)供多个线程访问 * 所以只在此处创建一个Computer对象作为实参传递给各个线程 */ Computer pc = new Computer(); //ThreadF和ThreadG都执行了pc的含同步块的非同步方法printer ThreadF tf = new ThreadF(pc); ThreadG tg = new ThreadG(pc); tf.start(); tg.start(); } } 运行结果: ThreadF-准备材料开始 ThreadG-准备材料开始 ThreadG-准备材料结束 ThreadG-打印材料开始 ThreadF-准备材料结束 ThreadG-打印材料结束 ThreadF-打印材料开始 ThreadF-打印材料结束
实例: package thread.wait; /** * 创建WaitDemo类 * 用于测试wait、notify、notifyAll方法 * @author 学霸联盟 - 赵灿 */ public class WaitDemo { public static void main(String[] args) { /* * 在这里创建一个唯一的Object对象onlyObject * 用于传递给以下三个线程使用,是为了保证三个线程使用的是同一对象 */ Object onlyObject = new Object(); /* * 创建三个线程对象ta、tb、tc * onlyObject会被赋值给每个线程的构造方法中的变量localObject * 相当于localObject = onlyObject; */ ThreadA ta = new ThreadA(onlyObject); ThreadB tb = new ThreadB(onlyObject); ThreadC tc = new ThreadC(onlyObject); //先启动线程ta和tb ta.start(); tb.start(); try { /* * 此处执行Thread.sleep(100);会是主线程休眠100毫秒 * 100毫秒后才会执行tc.start();启动线程tc * 目的是为了保证线程ta和tb中的wait方法先执行,阻塞住线程ta和tb * 然后在执行线程tc中的notify()方法是唤醒操作 * 否则如果先执行了唤醒操作,而后执行阻塞操作,将看不到唤醒的效果 */ Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } //启动线程tc tc.start(); } } /** * 创建ThreadA类 * 用于执行wait方法;阻塞操作 * @author 学霸联盟 - 赵灿 */ class ThreadA extends Thread { /* * 声明成员变量obj * 目的是因为在run方法中需要使用外部传进来的Object对象 * 但run方法中无法使用构造方法中的局部变量localObject * 所以此处声明一个成员变量obj用于接收外部传入的对象 * 这样以来run方法中,便可以通过成员变量obj可以使用外部传入的对象了 */ private Object obj; /* * 此处的localObject会接收到外部传入的Object类型的对象 * 并将其传递给成员变量obj */ public ThreadA(Object localObject) { //赋值给成员变量obj this.obj = localObject; } @Override public void run() { System.out.println("ThreadA--执行开始"); /* * 调用wait方法时,必须使用同步的方式获取调用wait方法对象的锁 * 否则会出现IllegalMonitorStateException异常 * 本例中,此处使用的是obj调用wait(obj.wait()) * 所以同步的也应该是obj(synchronized(obj) ) */ synchronized (obj) { try { System.out.println("ThreadA--被阻塞"); /* * 调用对象obj的wait方法,阻塞的将是执行这句代码的线程 * 本例中是执行此处代码的是线程ta,所以被阻塞的就是线程ta */ obj.wait(); System.out.println("ThreadA--被唤醒"); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("ThreadA--执行结束"); } } /** * 创建ThreadB类 * 用于执行wait方法;阻塞操作 * 其中的代码和ThreadA相同,就不再一一写注释了 * @author 学霸联盟 - 赵灿 */ class ThreadB extends Thread { private Object obj; public ThreadB(Object localObject) { this.obj = localObject; } @Override public void run() { synchronized (obj) { System.out.println("ThreadB--执行开始"); synchronized (obj) { try { System.out.println("ThreadB--被阻塞"); /* * 执行obj.wait(),阻塞的将是执行这句代码的线程 * 本例中是执行此处代码的是线程tb,所以被阻塞就是线程tb */ obj.wait(); System.out.println("ThreadB--被唤醒"); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("ThreadB--执行结束"); } } } /** * 创建ThreadC类 * 用于执行notify方法;唤醒操作 * @author 学霸联盟 - 赵灿 */ class ThreadC extends Thread { private Object obj; public ThreadC(Object localObject) { this.obj = localObject; } @Override public void run() { /* * 调用notify方法时,必须使用同步的方式获取调用notify方法对象的锁 * 否则会出现IllegalMonitorStateException异常 * 本例中,此处使用的是obj调用notify(obj.notify()) * 所以同步的也应该是obj(synchronized(obj) ) */ synchronized (obj) { System.out.println("ThreadC--唤醒最先被obj对象阻塞的线程"); /* * 执行obj.notify();将唤醒第一个被obj阻塞的线程 * 如果执行obj.notifyAll();所有被obj阻塞的线程都会被唤醒 */ obj.notify(); } } } 运行结果: ThreadA--执行开始 ThreadB--执行开始 ThreadB--被阻塞 ThreadA--被阻塞 ThreadC--唤醒最先被obj对象阻塞的线程 ThreadB--被唤醒 ThreadB--执行结束
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:java线程同步 关键字synchronized 同步方法和同步块 wait方法和notify方法 noti 线程调度
原文地址:http://blog.csdn.net/ixueba/article/details/47611371