对同一个对象进行多线程操作时,如何保证线程执行结果的一致性?我们需要对线程操作对象加同步锁。(这是一道面试题)
需求描述
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
1
2
3
4
5
6
7
8
9
10
11
12
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
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();
}
}
|
测试结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
"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 作为方法块使用时需要只能对对象加锁,不能是常用数据类型。
ab线程改进:使用线程等待和通知
athread.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
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()。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/boonya/article/details/86485504