首页 > 编程 > Java > 正文

Java线程使用同步锁交替执行打印奇数偶数的方法

2019-11-26 09:18:07
字体:
来源:转载
供稿:网友

对同一个对象进行多线程操作时,如何保证线程执行结果的一致性?我们需要对线程操作对象加同步锁。(这是一道面试题)

需求描述

1-20个数字

A线程打印奇数:1,3,5,7,9,11,13,15,17,19

B线程打印偶数:2,4,6,8,10,12,14,16,18,20

C线程在AB两个线程执行完了之后打印结果:“success”。

线程代码实现

Num.java

package com.boonya.thread.test; /** * @ClassName: Num * @Description: TODO(加锁计算对象) * @author: pengjunlin * @motto: 学习需要毅力,那就秀毅力 * @date 2019-01-14 22:47 */public class Num {  int value=1;}

AThread.java

package com.boonya.thread.test; /*** @ClassName: AThread* @Description: TODO(奇数线程)* @author: pengjunlin* @motto: 学习需要毅力,那就秀毅力* @date 2019-01-14 22:26*/public class AThread implements Runnable{   Num num;   public AThread(Num num){    this.num=num;  }   public void run() {    while (num.value<20){      synchronized (num){        if(num.value%2!=0){          System.out.println("AThread:"+ num.value);          num.value++;        }      }    }   }}

BThread.java

package com.boonya.thread.test; /** * @ClassName: BThread * @Description: TODO(偶数线程) * @author: pengjunlin * @motto: 学习需要毅力,那就秀毅力 * @date 2019-01-14 22:26 */public class BThread implements Runnable {     Num num;     public BThread(Num num){      this.num=num;    }     public void run() {      while (num.value<=20){        synchronized (num){          if(num.value%2==0){            System.out.println("BThread:"+ num.value);            num.value++;          }        }      }    } }

CThread.java

package com.boonya.thread.test; /** * @ClassName: CThread * @Description: TODO(等待结果线程) * @author: pengjunlin * @motto: 学习需要毅力,那就秀毅力 * @date 2019-01-14 22:26 */public class CThread implements Runnable {     Num num;     public CThread(Num num){      this.num=num;    }     public void run() {      while (num.value<20){        try {          Thread.sleep(1);        } catch (InterruptedException e) {          e.printStackTrace();        }      }      System.out.println("CThread:success!");    }  }

MainTest.java

package com.boonya.thread.test; import java.util.ArrayList;import java.util.List; /** * @ClassName: MainTest * @Description: TODO(线程测试) * @author: pengjunlin * @motto: 学习需要毅力,那就秀毅力 * @date 2019-01-14 21:54 */public class MainTest {   public static void main(String[] args) {    Num num=new Num();    Thread a=new Thread(new AThread(num));    Thread b=new Thread(new BThread(num));    Thread c=new Thread(new CThread(num));    a.start();    b.start();    c.start();  }}

测试结果

"C:/Program Files/Java/jdk1.8.0_121/bin/java" "-javaagent:C:/Users/boonya/AppData/Roaming/JetBrains/IntelliJ IDEA 2017.2.5/lib/idea_rt.jar=51911:C:/Users/boonya/AppData/Roaming/JetBrains/IntelliJ IDEA 2017.2.5/bin" -Dfile.encoding=UTF-8 -classpath "C:/Program Files/Java/jdk1.8.0_121/jre/lib/charsets.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/deploy.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/access-bridge-64.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/cldrdata.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/dnsns.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/jaccess.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/jfxrt.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/localedata.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/nashorn.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/sunec.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/sunjce_provider.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/sunmscapi.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/sunpkcs11.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/ext/zipfs.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/javaws.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/jce.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/jfr.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/jfxswt.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/jsse.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/management-agent.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/plugin.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/resources.jar;C:/Program Files/Java/jdk1.8.0_121/jre/lib/rt.jar;C:/Users/boonya/Desktop/JavaAlgorithm/target/test-classes;C:/Users/boonya/Desktop/JavaAlgorithm/target/classes" com.boonya.thread.test.MainTestAThread:1BThread:2AThread:3BThread:4AThread:5BThread:6AThread:7BThread:8AThread:9BThread:10AThread:11BThread:12AThread:13BThread:14AThread:15BThread:16AThread:17BThread:18AThread:19BThread:20CThread:success! Process finished with exit code 0

注意:synchronized 作为方法块使用时需要只能对对象加锁,不能是常用数据类型。

AB线程改进:使用线程等待和通知

AThread.java

package com.boonya.thread.test; /*** @ClassName: AThread* @Description: TODO(奇数线程)* @author: pengjunlin* @motto: 学习需要毅力,那就秀毅力* @date 2019-01-14 22:26*/public class AThread implements Runnable{   Num num;   public AThread(Num num){    this.num=num;  }   public void run() {    while (num.value<20){      synchronized (num){        if(num.value%2!=0){          System.out.println("AThread:"+ num.value);          num.value++;          //num.notify();          num.notifyAll();        }else{          try {            num.wait();          } catch (InterruptedException e) {            e.printStackTrace();          }        }      }    }   }}

BThread.java

package com.boonya.thread.test; /** * @ClassName: BThread * @Description: TODO(偶数线程) * @author: pengjunlin * @motto: 学习需要毅力,那就秀毅力 * @date 2019-01-14 22:26 */public class BThread implements Runnable {     Num num;     public BThread(Num num){      this.num=num;    }     public void run() {      while (num.value<=20){        synchronized (num){          if(num.value%2==0){            System.out.println("BThread:"+ num.value);            num.value++;            //num.notify();            num.notifyAll();          }else{            try {              num.wait();            } catch (InterruptedException e) {              e.printStackTrace();            }          }        }      }    } }

注:线程等待和通知的操作是节省CPU运算的一种方式,避免CPU空转(线程方法一直不停地跑类似于死循环是很可怕的),如果是要让线程停下来需要调用线程的wait()。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表