Java線程使用同步鎖交替執(zhí)行打印奇數(shù)偶數(shù)的方法
對(duì)同一個(gè)對(duì)象進(jìn)行多線程操作時(shí),如何保證線程執(zhí)行結(jié)果的一致性?我們需要對(duì)線程操作對(duì)象加同步鎖。(這是一道面試題)
需求描述
1-20個(gè)數(shù)字
A線程打印奇數(shù):1,3,5,7,9,11,13,15,17,19
B線程打印偶數(shù):2,4,6,8,10,12,14,16,18,20
C線程在AB兩個(gè)線程執(zhí)行完了之后打印結(jié)果:“success”。
線程代碼實(shí)現(xiàn)
Num.java
package com.boonya.thread.test;
/**
* @ClassName: Num
* @Description: TODO(加鎖計(jì)算對(duì)象)
* @author: pengjunlin
* @motto: 學(xué)習(xí)需要毅力,那就秀毅力
* @date 2019-01-14 22:47
*/
public class Num {
int value=1;
}
AThread.java
package com.boonya.thread.test;
/**
* @ClassName: AThread
* @Description: TODO(奇數(shù)線程)
* @author: pengjunlin
* @motto: 學(xué)習(xí)需要毅力,那就秀毅力
* @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(偶數(shù)線程)
* @author: pengjunlin
* @motto: 學(xué)習(xí)需要毅力,那就秀毅力
* @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(等待結(jié)果線程)
* @author: pengjunlin
* @motto: 學(xué)習(xí)需要毅力,那就秀毅力
* @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(線程測(cè)試)
* @author: pengjunlin
* @motto: 學(xué)習(xí)需要毅力,那就秀毅力
* @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è)試結(jié)果
"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.MainTest AThread:1 BThread:2 AThread:3 BThread:4 AThread:5 BThread:6 AThread:7 BThread:8 AThread:9 BThread:10 AThread:11 BThread:12 AThread:13 BThread:14 AThread:15 BThread:16 AThread:17 BThread:18 AThread:19 BThread:20 CThread:success! Process finished with exit code 0
注意:synchronized 作為方法塊使用時(shí)需要只能對(duì)對(duì)象加鎖,不能是常用數(shù)據(jù)類型。
AB線程改進(jìn):使用線程等待和通知
AThread.java
package com.boonya.thread.test;
/**
* @ClassName: AThread
* @Description: TODO(奇數(shù)線程)
* @author: pengjunlin
* @motto: 學(xué)習(xí)需要毅力,那就秀毅力
* @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(偶數(shù)線程)
* @author: pengjunlin
* @motto: 學(xué)習(xí)需要毅力,那就秀毅力
* @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();
}
}
}
}
}
}
注:線程等待和通知的操作是節(jié)省CPU運(yùn)算的一種方式,避免CPU空轉(zhuǎn)(線程方法一直不停地跑類似于死循環(huán)是很可怕的),如果是要讓線程停下來(lái)需要調(diào)用線程的wait()。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Flyway詳解及Springboot集成Flyway的詳細(xì)教程
Flayway是一款數(shù)據(jù)庫(kù)版本控制管理工具,,支持?jǐn)?shù)據(jù)庫(kù)版本自動(dòng)升級(jí),Migrations可以寫(xiě)成sql腳本,也可以寫(xiě)在java代碼里。這篇文章主要介紹了Flyway詳解及Springboot集成Flyway的詳細(xì)教程的相關(guān)資料,需要的朋友可以參考下2020-07-07
詳解Java的Hibernate框架中的緩存與原生SQL語(yǔ)句的使用
這篇文章主要介紹了Java的Hibernate框架中的緩存與原生SQL語(yǔ)句的使用,Hibernate是Java的SSH三大web開(kāi)發(fā)框架之一,需要的朋友可以參考下2015-12-12
Java中Elasticsearch 實(shí)現(xiàn)分頁(yè)方式(三種方式)
Elasticsearch是用Java語(yǔ)言開(kāi)發(fā)的,并作為Apache許可條款下的開(kāi)放源碼發(fā)布,是一種流行的企業(yè)級(jí)搜索引擎,這篇文章主要介紹了Elasticsearch實(shí)現(xiàn)分頁(yè)的3種方式,需要的朋友可以參考下2022-07-07
mybatis多對(duì)多關(guān)聯(lián)實(shí)戰(zhàn)教程(推薦)
下面小編就為大家?guī)?lái)一篇mybatis多對(duì)多關(guān)聯(lián)實(shí)戰(zhàn)教程(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10
Java實(shí)現(xiàn)學(xué)生成績(jī)輸出到磁盤(pán)文件的方法詳解
這篇文章主要為大家詳細(xì)介紹了如何利用Java實(shí)現(xiàn)將學(xué)生成績(jī)輸出到磁盤(pán)文件的功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-11-11
Java處理InterruptedException異常的理論與實(shí)踐
在使用Java的過(guò)程中,有個(gè)情景或許很多人見(jiàn)過(guò),您在編寫(xiě)一個(gè)測(cè)試程序,程序需要暫停一段時(shí)間,于是調(diào)用 Thread.sleep()。但是編譯器或 IDE 報(bào)錯(cuò)說(shuō)沒(méi)有處理檢查到的 InterruptedException。InterruptedException 是什么呢,為什么必須處理它?下面跟著小編一起來(lái)看看。2016-08-08

