-
synchronized关键字
-
Lock接口及其实现类,如ReentrantLock,ReentrantReadWriteLock.ReadLock和ReentrantReadWriteLock.WriteLock
-
信号量(Semaphore):一种计数器,用来保护一个或多个共享资源的访问。它是并发编程的一个基础工具。
-
CountDownLatch:是Java语言提供的同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许线程一直等待
-
CyclicBarrier:Java语言提供的同步辅助类,允许多个线程在某个集合点处进行相互等待
-
Phaser:它把并发任务分多个阶段运行,在开始下一个阶段之前,当前阶段中所有的线程都必须执行完成。
-
Exchanger:它提供了两个线程之间的数据交换点。
-
一个初始值,即定义必须等待的先行完成的操作数据;
-
await()方法,需要等待其他事件先完成的线程调用
-
countDown()方法,每个被等待的事件在完成操作后调用,使内部计数器减1.当内部计数器到达0时,countDownLatch对象将唤醒所有在await()方法上等待的线程
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
|
package
org.test.concurrency.phaser;
import
java.io.File;
import
java.util.ArrayList;
import
java.util.Date;
import
java.util.List;
import
java.util.concurrent.Phaser;
import
java.util.concurrent.TimeUnit;
/**
* <p>
* Title: FileSearch.java
* </p>
* <p>
* Description:
* </p>
* <p>
* Copyright: Copyright (c) 2016年6月11日
* </p>
* <p>
* Company:
* </p>
* Created on 2016年6月11日 上午8:32:06
*
* @author kucs FileSearch
*
* Description:创建文件查找类,实现runnable结构。
* 他将在一个文件夹及其子文件夹中查找过去24小时内修改过的指定扩展名的文件。
* -----------------------------------------------------
*
*/
public
class
FileSearch
implements
Runnable {
// 存储要查找额文件夹
private
String initPath;
// 存储要查找的文件的扩展名
private
String end;
// 存储查找到的文件的完整路径
private
List<String> results;
// 声明一个Phaser私有变量,用来控制任务不同阶段的同步
private
Phaser phaser;
public
FileSearch(String initPath, String end, Phaser phaser) {
this
.initPath = initPath;
this
.end = end;
this
.results =
new
ArrayList<>();
this
.phaser = phaser;
}
/**
* 实现辅助方法,他们将用于run方法中
*
*/
/**
* directoryProcess,用于处理所有文件和文件夹
*
* @param file
*/
public
void
directoryProcess(File file) {
File[] list = file.listFiles();
if
(list !=
null
&& list.length >
0
) {
for
(File f : list) {
if
(f.isDirectory()) {
directoryProcess(f);
}
else
{
fileProcess(f);
}
}
}
}
/** 用于查找这个传入的文件的扩展名是不是我们指定的,如果是,文件的绝对路径将被加入结果集中 */
private
void
fileProcess(File f) {
// TODO Auto-generated method stub
if
(f.getName().endsWith(end)) {
results.add(f.getAbsolutePath());
}
}
/** 对第一个阶段查找到的文件列表进行过滤,将不是24小时修改过的文件删除。 */
public
void
filterResults() {
List<String> newResult =
new
ArrayList<>();
long
actualDate =
new
Date().getTime();
for
(String strFilePath : results) {
File file =
new
File(strFilePath);
long
fileDate = file.lastModified();
if
(actualDate - fileDate < TimeUnit.MILLISECONDS.convert(
1
, TimeUnit.DAYS)) {
newResult.add(strFilePath);
}
}
results = newResult;
}
/** 将在第一个阶段和第二个阶段结束的时候用来检查结果集是不是空的 */
private
boolean
checkResults() {
if
(results.isEmpty()) {
System.out.printf(
"%s: Phaser %d: 0 results.\n"
, Thread.currentThread().getName(), phaser.getPhase());
System.out.printf(
"%s: Phaser %d: End.\n"
, Thread.currentThread().getName(), phaser.getPhase());
phaser.arriveAndDeregister();
return
false
;
}
else
{
System.out.printf(
"%s: Phaser %d: results.\n"
, Thread.currentThread().getName(), phaser.getPhase(),
results.size());
phaser.arriveAndAwaitAdvance();
return
true
;
}
}
/** 将结果集元素打印到控制台 */
private
void
showInfo() {
for
(String strFilePath : results) {
File file =
new
File(strFilePath);
System.out.printf(
"%s: %s\n"
, Thread.currentThread().getName(), file.getAbsolutePath());
}
phaser.arriveAndAwaitAdvance();
}
@Override
public
void
run() {
// TODO 调用Phaser对象的arriveAndAwaitAdvance()方法,使查找工作在所有线程都被创建之后再开始。
phaser.arriveAndAwaitAdvance();
System.out.printf(
"%s: Starting.\n"
, Thread.currentThread().getName());
File file =
new
File(initPath);
if
(file.isDirectory()) {
directoryProcess(file);
}
// 检查结果集是不是空的,如果是空的,结束对应线程,并使用return返回
if
(!checkResults()) {
return
;
}
// 对结果集进行过滤
filterResults();
// 检查结果集是不是空的,如果是空的,结束对应线程,并使用return返回
if
(!checkResults()) {
return
;
}
//将结果打印到控制台,撤销线程的注册,然后将线程完成信息打印到控制台
showInfo();
phaser.arriveAndDeregister();
System.out.printf(
"%s: Work completed.\n"
,Thread.currentThread().getName());
}
}
package
org.test.concurrency.phaser;
import
java.util.concurrent.Phaser;
public
class
PhaserMain {
public
static
void
main(String[] args) {
// TODO 创建一个Phaser对象,并指定参与阶段同步的线程是3个
Phaser phaser =
new
Phaser(
3
);
//定义要查到的文件目录,后缀
FileSearch system =
new
FileSearch(
"C:\\Windows"
,
"log"
, phaser);
FileSearch apps =
new
FileSearch(
"C:\\Program Files"
,
"log"
, phaser);
FileSearch document =
new
FileSearch(
"C:\\Documents And Settings"
,
"log"
, phaser);
Thread systemThread =
new
Thread(system,
"System"
);
systemThread.start();
Thread appsThread =
new
Thread(apps,
"Apps"
);
appsThread.start();
Thread documentThread =
new
Thread(document,
"Document"
);
documentThread.start();
try
{
systemThread.join();
appsThread.join();
documentThread.join();
}
catch
(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(
"Terminated: "
+phaser.isTerminated());
}
}
|
-
arrive():这个方法通知phaser对象一个参与者已经完成了当前阶段,java培训但是它不应该等待其他参与者都完成当前阶段。它不会与其他线程同步。
-
awaitAdvance(int phase):如果传入的阶段参数与当前阶段一直,这个方法会将当前线程置入休眠,知道这个阶段的所有 参与者都运行完成。如果传入的阶段参数与当前阶段不一致,这个方法就立即返回。
-
awaitAdvanceInterruptibly(int phaser):这个方法跟awaitAdvance(int phase)一个样,不同之处是,如果在这个方法中休眠的线程被中断,它将抛出InterruptedException。
-
register():这个方法将一个新的参与者注册到Phaser中,这个新的参与者将被当成执行本阶段的线程。
-
bulkRegister(int phaser):这个方法将指定数目的参与者注册到Phaser