线程

程序是一段静态的代码,它是应用软件执行的蓝本。
进程是程序的一次动态执行过程,它对应了从代码加载、执行至执行完毕的一个完整过程,这个过程也是进程本身从产生、发展至消亡(完成)的过程。
线程是比进程更小的执行单位。一个进程在其执行过程中,可以产生多个线程,形成多条执行线索。每条线索(即每个线程)有它自身的产生、发展和消亡(完成)的过程,也是一个动态的概念。

Java程序从主类(main class,main方法所在的类)的main()方法开始执行
当JVM加载代码,发现main()方法后,就会启动一个线程,称作“主线程”,该线程负责执行main()方法。
在main()方法中再创建的线程,就称为主线程中的线程

如果main()方法中创建了其他线程,那么JVM就要在主线程和其他线程之间轮流切换,保证每个线程都有机会使用CPU资源,main()方法即使执行完最后的语句,JVM也不会结束我们的程序,JVM一直要等到主线程中的所有线程都结束之后,才结束我们的Java应用程序。

线程的生命周期

Thread类或其子类创建的对象称作线程

新建

  • 有相应的内存空间和其他资源

运行

  • 线程必须调用start()方法(从父类继承的方法)通知JVM,则JVM就知道有一个新的线程排队等候切换
  • 当JVM将CPU使用权切换给线程时,线程是Thread类的子类创建的,则该类中的run()方法就立刻执行。所以我们必须在子类中重写(override)父类的run()方法。注:Thread类中的run()方法没有具体内容。
  • 在线程没有结束run()方法之前,不要让线程再调用start()方法,否则将发生IllegalThreadStateException异常。

中断

4种原因:

  • JVM将CPU资源从当前线程切换给其他线程,使本线程让出CPU的使用权,进而处于中断状态。
  • 线程使用CPU资源期间,执行了sleep(int millsecond)方法,使当前线程进入休眠状态。
  • 线程使用CPU资源期间,执行了wait()方法,使得当前线程进入中断(等待)状态。
    等待状态的线程不会主动进到线程队列中排队等待CPU资源,必须由其他线程调用notify()方法通知它,使得它重新进到线程队列中排队等待CPU资源,以便从中断处继续运行。
  • 线程使用CPU资源期间,执行某个操作进入中断(阻塞)状态,比如执行读/写操作引起阻塞。
    进入阻塞状态时线程不能进入排队队列,只有当引起阻塞的原因消除时,线程才重新进到线程队列中排队等待CPU资源,以便从原来中断处开始继续运行。

死亡

处于死亡状态的线程不具有继续运行的能力。线程释放了实体,即释放了分配给线程对象的内存.
线程死亡的原因:

  • 正常运行的线程完成了它的全部工作,即执行完run()方法中的全部语句,结束了run()方法。
  • 线程被提前强制终止,即强制run()方法结束。
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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
class WriteWordThread extends Thread
{
WriteWordThread(String s)
{
setName(s);
}
public void run()
{
for(int i=1; i<=3;i++)
System.out.println("Thread: " + getName());
}
}
public class Example8_1
{
public static void main(String args[])
{
WriteWordThread zhang, wang;
zhang = new WriteWordThread("Zhang"); //新建线程
wang = new WriteWordThread("Wang"); //新建线程
zhang.start(); //启动线程
for(int i=1; i<=3; i++)
{
System.out.println("Main Thread");
}
wang.start(); //启动线程
}
}
//计算机反复运行的结果不尽相同

//上述程序在不同的计算机运行或在同一台计算机反复运行的结果不尽相同,输出结果依赖当前CPU资源的使用情况。
//为了使结果尽量不依赖当前CPU资源的使用情况,我们应当让线程主动调用sleep方法让出CPU的使用权进入中断状态。

class WriteWordThread extends Thread
{
int n = 0;
WriteWordThread(String s, int n)
{
setName(s);
this.n = n;
}
public void run()
{
for(int i=1; i<=3; i++)
{
System.out.println("Thread: " + getName());
try
{
sleep(n);
}
catch(InterruptedException e) {}
}
}
}
public class Example8_2
{
public static void main(String args[])
{
WriteWordThread zhang, wang;
zhang = new WriteWordThread("Zhang", 200);
wang = new WriteWordThread("Wang", 100);
zhang.start();
wang.start();
}
}
//计算机反复运行的结果不尽相同

线程的优先级与调度管理

  • JVM中的线程调度器负责管理线程,调度器把线程的优先级分为10个级别,分别用Thread类中的类静态常量表示。每个Java线程的优先级都在常数1(Thread.MIN_PRIORITY)到常数10(Thread.MAX_PRIORITY)的范围内。
  • 如果没有明确设置线程的优先级,每个线程的优先级都为常数5(Thread.NORM_PRIORITY)
  • 线程的优先级可以通过setPriority(int grade)方法调整,这一方法需要一个int类型参数。如果此参数不在1-10的范围内,那么setPriority便产生一个lllegalArgumentException异常。
  • getPriority方法返回线程的优先级。需要注意是,有些操作系统只能识别3个级别:1、5和10。
  • JVM中的线程调度器使高优先级的线程能有更高的概率运行。

Thread的子类创建线程

继承Thread类,重写父类的run()方法
主线程使用exit(int n)方法结束整个程序

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class Left extends Thread
{
int n = 0;
public void run()
{
while(true)
{
n++;
System.out.println(n+"Left");
try
{
sleep((int)(Math.random()*100));
}
catch(InterruptedException e) {}
}
}
}
class Right extends Thread
{
int n = 0;
public void run()
{
while(true)
{
n++;
System.out.println(n+"Right");
try
{
sleep((int)(Math.random()*100));
}
catch(InterruptedException e){}
}
}
}
public class Example8_3
{
public static void main(String args[])
{
Left left = new Left();
Right right = new Right();
left.start();
right.start();
while(true)
{
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(left.n>=8 || right.n>=8)
{
System.out.println(left.n + "," + right.n);
System.exit(0);
}
}
}
}

Runnable接口

Runnable接口与目标对象

创建线程的另一个途径就是用Thread类直接创建线程对象Thread(Runnable task)
实现Runnable接口的类的实例对象task称作所创建线程的目标对象target,当线程调用start()方法后,一旦轮到它来享用CPU资源,目标对象就会自动调用接口中的run()方法(接口回调)。

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//两个线程共享一个实例对象taskBank,则money随其变化
class TaskBank implements Runnable //实现Runnable接口的类
{
private int money = 0;
String name1,name2;
TaskBank(String s1, String s2){ name1 = s1; name2 = s2; }
public void setMoney(int mount){ money = mount; }
public void run()
{
while(true)
{
money = money-10;
if(Thread.currentThread().getName().equals(name1))
{
System.out.println(name1 + ": " + money);
if(money<=100)
{
System.out.println(name1 + ": Finished");
return;
}
}
else if(Thread.currentThread().getName().equals(name2))
{
System.out.println(name2 + ": " + money);
if(money<=60)
{
System.out.println(name2 + ": Finished");
return;
}
}
try{ Thread.sleep(800); }
catch(InterruptedException e) {}
}
}
}
public class Example8_4
{
public static void main(String args[])
{
String s1="treasurer zhang"; // 会计
String s2="cashier cheng"; // 出纳
TaskBank taskBank = new TaskBank(s1,s2); //实现Runnable接口的类的实例
taskBank.setMoney(120);

Thread zhang;
Thread cheng;
zhang = new Thread(taskBank); // 目标对象bank
cheng = new Thread(taskBank); // 目标对象bank
zhang.setName(s1);
cheng.setName(s2);
zhang.start();
cheng.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// threadA和threadB的目标对象a1
// threadA和threadB共享a1的成员number

// threadC和threadD的目标对象是a2
// threadC和threadD共享a2的成员number

class Task implements Runnable
{
private int number = 0; //共享成员变量
public void setNumber(int n)
{
number = n;
}
public void run()
{
while(true)
{
if(Thread.currentThread().getName().equals("add"))
{
number++;
System.out.printf("%d\n",number);
}
if(Thread.currentThread().getName().equals("sub"))
{
number--;
System.out.printf("%12d\n",number);
}
try{ Thread.sleep(1000); }
catch(InterruptedException e) {}
}
}
}
public class Example8_5
{
public static void main(String args[])
{
Task taskAdd = new Task(); //目标对象
taskAdd.setNumber(10);
Task taskSub = new Task(); //目标对象
taskSub.setNumber(-10);

Thread threadA,threadB,threadC,threadD; //四个线程
threadA = new Thread(taskAdd);
threadB = new Thread(taskAdd);
threadA.setName("add");
threadB.setName("add");
threadC = new Thread(taskSub);
threadD = new Thread(taskSub);
threadC.setName("sub");
threadD.setName("sub");
threadA.start();
threadB.start();
threadC.start();
threadD.start();
}
}

关于run()方法中的局部变量

不同线程的run()方法中的局部变量互不干扰

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
class TaskAddSub implements Runnable
{
String s1,s2;
TaskAddSub(String s1,String s2){this.s1=s1; this.s2=s2;}
public void run()
{
int i=0; //局部变量
while(true)
{
if(Thread.currentThread().getName().equals(s1))
{
i=i+1;
System.out.println(s1 + ":" + i);
if(i>=4)
{
System.out.println(s1 + "Finished");
return;
}
}
else if(Thread.currentThread().getName().equals(s2))
{
i=i-1;
System.out.println(s2 + ":" + i);
if(i<=-4)
{
System.out.println(s2 + "Finished");
return;
}
}
try{ Thread.sleep(800); }
catch(InterruptedException e) {}
}
}
}
public class Example8_6
{
public static void main(String args[])
{
String s1 = "ZHANG San";
String s2 = "LI Si";
TaskAddSub taskAddSub = new TaskAddSub(s1,s2);

Thread zhang, li;
zhang = new Thread(taskAddSub);
li = new Thread(taskAddSub);
zhang.setName(s1);
li.setName(s2);
zhang.start();
li.start();
}
}

线程的常用方法

start()启动线程
run()Thread类的run()方法与Runnable接口中的run()方法的功能和作用相同,都用来定义线程对象被调度之后所执行的操作。系统自动调用而用户程序不可以调用.
sleep(int millsecond)休眠
isAlive()线程的run()方法结束前/没有进入死亡状态前/未调用start()方法前,线程调用isAlive()方法返回true。线程进入死亡状态后(实体内存被释放),线程仍可以调用方法isAlive(),返回的值是false。
一个已经运行的线程在没有进入死亡状态前,不要再给线程分配实体
currentThread()返回当前正在使用CPU资源的线程
interrupt()用来“吵醒”休眠的线程.
当一些线程调用sleep()方法处于休眠状态时,一个使用CPU资源的其它线程在执行过程中,可以让休眠的线程分别调用interrupt()方法“吵醒”自己,即导致休眠的线程发生InterruptedException异常,从而结束休眠,重新排队等待CPU资源。

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
38
39
40
41
42
43
44
45
46
47
48
class TaskClassRoom implements Runnable
{
Thread teacher, zhang, li;
TaskClassRoom()
{
teacher = new Thread(this); zhang = new Thread(this); li = new Thread(this);
zhang.setName("Zhang"); li.setName("Li"); teacher.setName("Pan");
}

public void run()
{
Thread thread = Thread.currentThread();
if(thread==zhang || thread==li)
{
try
{
System.out.println(thread.getName() + ": Sleep for 10s");
Thread.sleep(10000);
}
catch(InterruptedException e)
{
System.out.println(thread.getName() + ": been wake up");
}
System.out.println(thread.getName() + ": Good morning");
}
else if(thread==teacher)
{
for(int i=1;i<=3;i++)
{
System.out.println(thread.getName() + ": Let's start ...");
try{ Thread.sleep(500); }
catch(InterruptedException e) {}
}
zhang.interrupt(); // zhang吵醒自己
li.interrupt(); // li吵醒自己
}
}
}
public class Example8_8
{
public static void main(String args[])
{
TaskClassRoom taskClassRoom = new TaskClassRoom(); // target
taskClassRoom.zhang.start();
taskClassRoom.li.start();
taskClassRoom.teacher.start();
}
}

线程同步

多个线程要执行一个synchronized修饰的方法

线程A在占有CPU资源期间,调用执行synchronized方法,
那么在synchronized方法返回前(即synchronized方法调用执行完毕之前),
其他占有CPU资源的线程一旦调用这个synchronized方法就会引起堵塞
堵塞的线程一直要等到堵塞的原因消除( 即synchronized方法返回),再排队等待CPU资源,以便使用这个同步方法。

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
38
39
40
41
42
43
44
45
46
class Bank implements Runnable
{
int money = 300; //共享
String treasurerName, cashierName;
public Bank(String s1,String s2){ treasurerName=s1; cashierName=s2; }
public void run(){ saveOrTake(30); }
public synchronized void saveOrTake(int number) //
{
if(Thread.currentThread().getName().equals(treasurerName))
{
for(int i=1;i<=3;i++)
{
money = money + number;
try { Thread.sleep(1000); }
catch(InterruptedException e) {}
System.out.println(treasurerName + " : " + money);
}
}
else if(Thread.currentThread().getName().equals(cashierName))
{
for(int i=1;i<=2;i++)
{
money = money-number/2;
try{ Thread.sleep(1000);}
catch(InterruptedException e){}
System.out.println(cashierName + " : " + money);
}
}
}
}
public class Example8_9
{
public static void main(String args[])
{
String treasurerName = "Treaurer", cashierName = "Cashier";
Bank bank = new Bank(treasurerName, cashierName);

Thread treasurer, cashier;
treasurer = new Thread(bank); // 目标对象bank
cashier = new Thread(bank); // 目标对象bank
treasurer.setName(treasurerName);
cashier.setName(cashierName);
treasurer.start();
cashier.start();
}
}

使用wait(),notify(),notifyAll()协调同步线程

wait(), notify()和notifyAll()都是Object类中的final方法,是被所有的类继承、且不允许重写的方法。

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
class TicketSeller
{
int fiveNumber=1, tenNumber=0, twentyNumber=0; //共享
public synchronized void sellTicket(int receiveMoney)
{
String s=Thread.currentThread().getName();
if(receiveMoney==5)
{
fiveNumber = fiveNumber+1;
System.out.println(s + " gives $5 to seller, seller gives " + s + " a ticket");
}
else if(receiveMoney==10){
while(fiveNumber<1){
try{ System.out.println(s + " gives $10 to seller");
System.out.println("seller asks " + s + " to wait");
wait();//中断方法的执行,使本线程等待,暂时让出CPU的使用权,并允许其它线程使用这个同步方法。
System.out.println(s + " stops waiting and starts to buy...");
}
catch(InterruptedException e){}
}
fiveNumber=fiveNumber-1;
tenNumber=tenNumber+1;
System.out.println(s + " gives $10 to seller, seller gives " + s + " a ticket and $5");
}
else if(receiveMoney==20){
while(fiveNumber<1||tenNumber<1){
try{ System.out.println(s + " gives $20 to seller");
System.out.println("seller asks " + s + " to wait");
wait();
System.out.println(s+" stops waiting and starts to buy ...");
}
catch(InterruptedException e){}
}
fiveNumber = fiveNumber-1;
tenNumber = tenNumber-1;
twentyNumber = twentyNumber+1;
System.out.println(s + " gives $20 to seller, seller gives " + s + " a ticket and $15");
}
notifyAll(); //通知所有由于使用这个同步方法而处于等待的线程结束等待
}
}
class Cinema implements Runnable
{
TicketSeller seller;
String name1, name2, name3;
Cinema(String s1,String s2,String s3)
{
seller = new TicketSeller();
name1 = s1;
name2 = s2;
name3 = s3;
}
public void run()
{
if(Thread.currentThread().getName().equals(name1))
{
seller.sellTicket(20);
}
else if(Thread.currentThread().getName().equals(name2))
{
seller.sellTicket(10);
}
else if(Thread.currentThread().getName().equals(name3))
{
seller.sellTicket(5);
}
}
}
public class Example8_10
{
public static void main(String args[])
{
String s1="Zhang", s2="Sun", s3="Zhao";
Cinema cinema = new Cinema(s1,s2,s3);

Thread zhang, sun, zhao;
zhang = new Thread(cinema); // 目标对象cinema
sun = new Thread(cinema); // 目标对象cinema
zhao = new Thread(cinema); // 目标对象cinema
zhang.setName(s1);
sun.setName(s2);
zhao.setName(s3);
zhang.start();
sun.start();
zhao.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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
//线程thread每隔一秒钟输出一个整数,输出3个整数后,该线程挂起
class A implements Runnable{
int number = 0;
volatile boolean stop = false;//声明为volatile,则变量值修改后对其他线程(例如,主线程)是可见的
boolean getStop(){ return stop; }
public void run(){
while(true)
{
number++;
System.out.println(Thread.currentThread().getName() + " : " + number);
if(number==3)
{
try{
System.out.println(Thread.currentThread().getName() + " : hang up");
stop = true;
hangUP(); //挂起
System.out.println(Thread.currentThread().getName() + " : resumed");
}
catch(Exception e){}
}
try{ Thread.sleep(1000); }
catch(Exception e){}
}
}
public synchronized void hangUP() throws InterruptedException{ wait(); }
public synchronized void restart(){ notifyAll(); }
}
public class Example8_11
{
public static void main(String args[])
{
A target = new A();
Thread thread = new Thread(target);
thread.setName("Zhang San");
thread.start();

while(target.getStop()==false)
{
try{ Thread.sleep(1000); }
catch(Exception e){}
}

System.out.println("Main Thread");
target.restart(); //恢复thread线程继续执行
}
}

线程联合

  • 一个线程A在占有CPU资源期间,可以让线程B调用join()方法和本线程联合
    如:B.join(); 我们称A在运行期间联合了B。
  • 线程A在占有CPU资源期间联合B线程,则A线程立刻中断执行,等到它联合的线程B执行完毕,A线程再重新排队等待CPU资源,以便恢复执行。
    如果A线程准备联合的B线程已经结束,那么B.join()不会产生任何效果
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
38
39
40
41
42
class JoinThread implements Runnable
{
Thread threadA, threadB;
String content[] = {"今天晚上,", "大家不要", "回去的太早,", "还有工作", "需要大家做!"};
JoinThread()
{
threadA=new Thread(this);
threadB=new Thread(this);
threadB.setName("经理");
}
public void run()
{
if(Thread.currentThread()==threadA)
{
System.out.println("我等"+threadB.getName()+"说完再说话");
threadB.start();
while(threadB.isAlive()==false){}

try{ threadB.join(); }
catch(InterruptedException e){}
System.out.printf("\n我开始说话:\"我明白你的意思了,谢谢\"");
}
else if(Thread.currentThread()==threadB)
{
System.out.println(threadB.getName()+"说:");
for(int i=0;i<content.length;i++)
{
System.out.print(content[i]);
try { threadB.sleep(1000); }
catch(InterruptedException e){}
}
}
}
}
public class Example8_13
{
public static void main(String args[])
{
JoinThread a = new JoinThread();
a.threadA.start();
}
}

守护线程

  • 一个线程调用void setDaemon(boolean on)方法可以将自己设置成一个守护(daemon)线程,例如:thread.setDaemon(true);
  • 线程默认是非守护线程,非守护线程也称作用户(user)线程
  • 当程序中的所有用户线程都已结束运行时,即使守护线程的run()方法中还有需要执行的语句,守护线程也立刻结束运行
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
38
39
class TaskDaemon implements Runnable{
Thread A,B;
TaskDaemon()
{
A = new Thread(this);
B = new Thread(this);
}
public void run()
{
if(Thread.currentThread()==A)
{
for(int i=0;i<3;i++)
{
System.out.println("i="+i) ;
try { Thread.sleep(1000); }
catch(InterruptedException e){}
}
}
else if(Thread.currentThread()==B)
{
while(true)
{
System.out.println("线程B是守护线程 ");
try{ Thread.sleep(1000); }
catch(InterruptedException e){}
}
}
}
}
public class Example8_14
{
public static void main(String args[])
{
TaskDaemon a=new TaskDaemon();
a.A.start();
a.B.setDaemon(true); //守护线程
a.B.start();
}
}

线程池

thread pool
an ideal way to manage the number of tasks executing concurrently.
管理并发执行的任务
Executor 接口用于执行线程池中的任务,
ExecutorService 是 Executor 的一个子接口,用于管理和控制任务

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class PrintChar implements Runnable 
{
private char charToPrint;
private int times;

public PrintChar(char c, int t)
{
charToPrint = c;
times = t;
}

@Override
public void run()
{
for (int i = 0; i < times; i++)
{
System.out.print(charToPrint);
}
}
}
class PrintNum implements Runnable
{
private int lastNum;

public PrintNum(int n)
{
lastNum = n;
}

@Override
public void run() {
for (int i = 1; i <= lastNum; i++)
{
System.out.print(" " + i);
}
}
}

//原来写法:为每个任务创建一个线程
public class TaskThreadDemo
{
public static void main(String[] args)
{
//Create tasks
Runnable printA = new PrintChar('a', 100);
Runnable printB = new PrintChar('b', 100);
// Runnable printA = new PrintChar('a', 600);
// Runnable printB = new PrintChar('b', 600);
Runnable print100 = new PrintNum(100);
// Create threads
Thread thread1 = new Thread(printA);
Thread thread2 = new Thread(printB);
Thread thread3 = new Thread(print100);
// Start threads
thread1.start();
thread2.start();
thread3.start();
}
}

//use线程池:
import java.util.concurrent.*;

public class ExecutorDemo
{
public static void main(String[] args)
{
ExecutorService executor= Executors.newFixedThreadPool(3); //create
executor.execute(new PrintChar('a', 100));
executor.execute(new PrintChar('b', 100));
executor.execute(new PrintNum( 100));
executor.shutdown(); //shutdown
}
}

锁->线程同步

Synchronization Using Locks

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import java.util.concurrent.*;
import java.util.concurrent.locks.*;

// 静态内部类Account,用于模拟银行账户
public class AccountWithSyncUsingLock
{
private static Account account = new Account();//定义一个共享的Account对象

public static void main(String[] args)
{
ExecutorService executor = Executors.newCachedThreadPool();//创建线程池

//提交100个任务到线程池,每个任务向账户中存入1分钱
for (int i = 0; i < 100; i++) {
executor.execute(new AddAPennyTask());
}
executor.shutdown();// 关闭线程池,不再接受新任务
//等待直到所有任务执行完成
while (!executor.isTerminated()) {}
//打印最终账户余额
System.out.println("what is balance?" + account.getBalance());
}

//内部类AddAPennyTask,实现Runnable接口,用于向账户存钱的任务
public static class AddAPennyTask implements Runnable
{
public void run() {
account.deposit(1); // 向账户存入1分钱
}
}

//内部类Account,模拟银行账户的操作
//静态内部类:外部类需使用内部类,而内部类无需外部类资源,且内部类可单独创建对象。
private static class Account
{
private static Lock lock = new ReentrantLock(); //创建锁
private int balance = 0;// 账户初始余额为0

public int getBalance() {
return balance; //获取当前余额
}

public void deposit(int amount)
{
lock.lock(); //上锁
try
{
int newBalance = balance + amount;// 计算新的余额
Thread.sleep(5);
balance = newBalance;// 更新账户余额
}
catch (InterruptedException ex) {
}
finally{
lock.unlock(); //关锁
}
}
}
}
// what is balance?100

线程合作

Cooperation among Threads

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
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import java.util.concurrent.*;
import java.util.concurrent.locks.*;

public class ThreadCooperation
{
private static Account account = new Account();
//创建含有两个线程的线程池
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.execute(new DepositTask());
executor.execute(new WithdrawTask());
executor.shutdown();
}
public static class DepositTask implements Runnable { //存钱线程
@Override
public void run() {
try{
while(true){
account.deposit((int)(Math.random()*10)+1);
Thread.sleep(1000);
}
}
catch (InterruptedException ex){
ex.printStackTrace();
}
}
}
public static class WithdrawTask implements Runnable { //存钱线程
@Override
public void run() {
while(true){
account.withdraw((int)(Math.random()*10)+1);
}
}
}

private static class Account //内部类
{
private static Lock lock = new ReentrantLock(); //创建锁
private static Condition newDeposit = lock.newCondition(); //创建条件
private int balance;
public int getBalance() { //获取账户余额
return balance;
}
public void withdraw(int amount) //取钱
{
lock.lock();
try{
while(balance<amount){
System.out.println("\t\tWaiting for deposit");
newDeposit.await(); //等待
}
balance -= amount;
System.out.println("\t\tWithdraw " + amount+"\t\t"+getBalance());
}
catch (InterruptedException ex){
ex.printStackTrace();
}
finally{
lock.unlock();
}
}
public void deposit(int amount) //存钱
{
lock.lock();
try{
balance += amount;
System.out.println("\t\tDeposit " + amount+"\t\t\t\t\t"+getBalance());
newDeposit.signalAll(); //提醒线程等待结束,继续
}
finally{
lock.unlock();
}
}
}
}