use*_*407 0 java multithreading executorservice
为什么我在下面的代码中没有将 list1 和 list2 的列表大小设置为 1000:
我的主要方法代码如下:
ExecutorService executor = Executors.newFixedThreadPool(2);
for(int j=0; j<2; j++) {
executor.submit(new Worker(j));
}
executor.shutdown();
System.out.println("All tasks submitted: ");
try {
executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
}
long end = System.currentTimeMillis();
System.out.println("Time taken: " + (end - start));
System.out.println("List1: " + list1.size() + "; List2: " + list2.size());
Run Code Online (Sandbox Code Playgroud)
在这里Worker
上课:
class Worker implements Runnable{
private int id;
public Worker(int id) {
this.id = id;
}
private Random random = new Random();
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void stageOne() {
synchronized(lock1) {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
WorkerThreadPool.list1.add(random.nextInt(100));
}
}
public void stageTwo() {
synchronized(lock2) {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
WorkerThreadPool.list2.add(random.nextInt(100));
}
}
public void process() {
for(int i=0; i<500; i++) {
stageOne();
stageTwo();
}
}
@Override
public void run() {
System.out.println("Starting thread: " + id);
process();
System.out.println("Completed: " + id);
}
}
Run Code Online (Sandbox Code Playgroud)
在一次跑步时,我得到了
List1: 986; List2: 989
Run Code Online (Sandbox Code Playgroud)
其他时间我得到
List1: 994; List2: 981
Run Code Online (Sandbox Code Playgroud)
但每次它应该给
List1: 1000; List2: 1000
Run Code Online (Sandbox Code Playgroud)
这里有什么问题?
class Worker implements Runnable{
private int id;
public Worker(int id) {
this.id = id;
}
private Random random = new Random();
private final Object lock1 = new Object();
private final Object lock2 = new Object();
.....
Run Code Online (Sandbox Code Playgroud)
结果是不可预测的,因为线程不共享锁。
在这里,lock1
和lock2
没有任何意义。
这是因为:当您在WorkerThreadPool
using 中提交任务时executor.submit(new Worker(j));
,每个线程都会获得自己的副本locks
(每个Worker
实例都创建新的lock1
和lock2
)。
这里更新Worker
了sharedLock逻辑:
class Worker implements Runnable {
private int id;
Object sharedLock;
public Worker(int id, Object sharedLock) {
this.id = id;
this.sharedLock = sharedLock;
}
private Random random = new Random();
public void stageOne() {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (sharedLock) {
WorkerThreadPool.list1.add(random.nextInt(100));
}
}
public void stageTwo() {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
synchronized (sharedLock) {
WorkerThreadPool.list2.add(random.nextInt(100));
}
}
public void process() {
for (int i = 0; i < 500; i++) {
stageOne();
stageTwo();
}
}
@Override
public void run() {
System.out.println("Starting thread: " + id);
process();
System.out.println("Completed: " + id);
}
}
Run Code Online (Sandbox Code Playgroud)
更新WorkerThreadPool
:
public class WorkerThreadPool {
public static List<Integer> list1 = new ArrayList<>();
public static List<Integer> list2 = new ArrayList<>();
static Object sharedLock = new Object(); // share lock
public static void main(String[] args) {
long start = System.currentTimeMillis();
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int j = 0; j < 2; j++) {
executor.submit(new Worker(j, sharedLock)); // pass same lock to each instance of Worker
}
executor.shutdown();
System.out.println("All tasks submitted: ");
try {
executor.awaitTermination(1, TimeUnit.DAYS);
} catch (InterruptedException e) {
}
long end = System.currentTimeMillis();
System.out.println("Time taken: " + (end - start));
System.out.println("List1: " + list1.size() + "; List2: " + list2.size());
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
All tasks submitted:
Starting thread: 1
Starting thread: 0
Completed: 0
Completed: 1
Time taken: 1842
List1: 1000; List2: 1000
Run Code Online (Sandbox Code Playgroud)