在 ExecutorService 中没有得到想要的结果
not getting the desired result in 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());
这里是 Worker
class:
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);
}
}
一次运行我得到
List1: 986; List2: 989
我得到的其他时间
List1: 994; List2: 981
但每次都应该给
List1: 1000; List2: 1000
这是怎么回事?
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();
.....
结果不可预测,因为线程没有共享锁。
在这里,lock1
和 lock2
没有任何用处。
原因是:当您使用 executor.submit(new Worker(j));
在 WorkerThreadPool
中提交任务时,每个线程都会获得自己的 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);
}
}
已更新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());
}
}
输出:
All tasks submitted:
Starting thread: 1
Starting thread: 0
Completed: 0
Completed: 1
Time taken: 1842
List1: 1000; List2: 1000
为什么我没有将 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());
这里是 Worker
class:
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);
}
}
一次运行我得到
List1: 986; List2: 989
我得到的其他时间
List1: 994; List2: 981
但每次都应该给
List1: 1000; List2: 1000
这是怎么回事?
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();
.....
结果不可预测,因为线程没有共享锁。
在这里,lock1
和 lock2
没有任何用处。
原因是:当您使用 executor.submit(new Worker(j));
在 WorkerThreadPool
中提交任务时,每个线程都会获得自己的 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);
}
}
已更新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());
}
}
输出:
All tasks submitted:
Starting thread: 1
Starting thread: 0
Completed: 0
Completed: 1
Time taken: 1842
List1: 1000; List2: 1000