FairSync 能保证执行顺序吗?
Can FairSync guarantee the order of execution?
我的第一个问题,感谢您的帮助!
我正在尝试使用两个线程交替打印奇数和偶数 1~100。
预期结果:
pool-1-thread-1=> 1
pool-1-thread-2=> 2
pool-1-thread-1=> 3
pool-1-thread-2=> 4
......
pool-1-thread-1=> 99
pool-1-thread-2=> 100
我想我可以使用FairSync,但它只能保证大部分打印是正确的。像这样:
pool-1-thread-1=> 55
pool-1-thread-2=> 56
pool-1-thread-1=> 57
pool-1-thread-2=> 58
pool-1-thread-2=> 59 //※error print※
pool-1-thread-1=> 60
pool-1-thread-2=> 61
pool-1-thread-1=> 62
不知道为什么丢单的情况很少?
你可以批评我的代码和我的英语。
这是我的代码:
private static final int COUNT = 100;
private static final int THREAD_COUNT = 2;
private static int curr = 1;
static ReentrantLock lock = new ReentrantLock(true);
static ExecutorService executorService = Executors.newCachedThreadPool();
public static void main(String[] args) {
Runnable task = () -> {
for (; ; ) {
try {
lock.lock();
if (curr <= COUNT) {
System.out.println(Thread.currentThread().getName() + "=> " + curr++);
} else {
System.exit(0);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
for (int i = 0; i < THREAD_COUNT; i++) {
executorService.execute(task);
}
}
不,亲爱的,您的实施不正确。哪个线程获得 运行 的机会由 OS 决定。不能保证线程1&2会依次执行。
您可以通过检查变量 curr 的先前值来修复您的代码,如果该值不是此线程期望的值,则不要递增和打印。
例如:
if(curr.threadName.equals("Thread 2") && (curr%2 !=0))
{
// Print
// Increment
}
您不能使用单锁来实现此目的。即使 ReentrantLock
提供公平性,但它无法控制线程调度。
我们可以像Semaphore
一样实现throw线程间通信。信号量控制线程的执行。
我们创建了两个线程,一个奇数线程和一个偶数线程。奇数线程打印从1开始的奇数,偶数线程打印从2开始的偶数。
创建两个信号量,semOdd 和 semEven,它们将具有 1 和 0 许可。这将确保首先打印奇数。
class SharedPrinter {
private Semaphore semEven = new Semaphore(0);
private Semaphore semOdd = new Semaphore(1);
void printEvenNum(int num) {
try {
semEven.acquire();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + num);
semOdd.release();
}
void printOddNum(int num) {
try {
semOdd.acquire();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + num);
semEven.release();
}
}
class Even implements Runnable {
private SharedPrinter sp;
private int max;
// standard constructor
@Override
public void run() {
for (int i = 2; i <= max; i = i + 2) {
sp.printEvenNum(i);
}
}
}
class Odd implements Runnable {
private SharedPrinter sp;
private int max;
// standard constructors
@Override
public void run() {
for (int i = 1; i <= max; i = i + 2) {
sp.printOddNum(i);
}
}
}
public static void main(String[] args) {
SharedPrinter sp = new SharedPrinter();
Thread odd = new Thread(new Odd(sp, 10),"Odd");
Thread even = new Thread(new Even(sp, 10),"Even");
odd.start();
even.start();
}
参考:here
我的第一个问题,感谢您的帮助! 我正在尝试使用两个线程交替打印奇数和偶数 1~100。 预期结果:
pool-1-thread-1=> 1
pool-1-thread-2=> 2
pool-1-thread-1=> 3
pool-1-thread-2=> 4
......
pool-1-thread-1=> 99
pool-1-thread-2=> 100
我想我可以使用FairSync,但它只能保证大部分打印是正确的。像这样:
pool-1-thread-1=> 55
pool-1-thread-2=> 56
pool-1-thread-1=> 57
pool-1-thread-2=> 58
pool-1-thread-2=> 59 //※error print※
pool-1-thread-1=> 60
pool-1-thread-2=> 61
pool-1-thread-1=> 62
不知道为什么丢单的情况很少? 你可以批评我的代码和我的英语。 这是我的代码:
private static final int COUNT = 100;
private static final int THREAD_COUNT = 2;
private static int curr = 1;
static ReentrantLock lock = new ReentrantLock(true);
static ExecutorService executorService = Executors.newCachedThreadPool();
public static void main(String[] args) {
Runnable task = () -> {
for (; ; ) {
try {
lock.lock();
if (curr <= COUNT) {
System.out.println(Thread.currentThread().getName() + "=> " + curr++);
} else {
System.exit(0);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
};
for (int i = 0; i < THREAD_COUNT; i++) {
executorService.execute(task);
}
}
不,亲爱的,您的实施不正确。哪个线程获得 运行 的机会由 OS 决定。不能保证线程1&2会依次执行。
您可以通过检查变量 curr 的先前值来修复您的代码,如果该值不是此线程期望的值,则不要递增和打印。
例如:
if(curr.threadName.equals("Thread 2") && (curr%2 !=0))
{
// Print
// Increment
}
您不能使用单锁来实现此目的。即使 ReentrantLock
提供公平性,但它无法控制线程调度。
我们可以像Semaphore
一样实现throw线程间通信。信号量控制线程的执行。
我们创建了两个线程,一个奇数线程和一个偶数线程。奇数线程打印从1开始的奇数,偶数线程打印从2开始的偶数。
创建两个信号量,semOdd 和 semEven,它们将具有 1 和 0 许可。这将确保首先打印奇数。
class SharedPrinter {
private Semaphore semEven = new Semaphore(0);
private Semaphore semOdd = new Semaphore(1);
void printEvenNum(int num) {
try {
semEven.acquire();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + num);
semOdd.release();
}
void printOddNum(int num) {
try {
semOdd.acquire();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println(Thread.currentThread().getName() + num);
semEven.release();
}
}
class Even implements Runnable {
private SharedPrinter sp;
private int max;
// standard constructor
@Override
public void run() {
for (int i = 2; i <= max; i = i + 2) {
sp.printEvenNum(i);
}
}
}
class Odd implements Runnable {
private SharedPrinter sp;
private int max;
// standard constructors
@Override
public void run() {
for (int i = 1; i <= max; i = i + 2) {
sp.printOddNum(i);
}
}
}
public static void main(String[] args) {
SharedPrinter sp = new SharedPrinter();
Thread odd = new Thread(new Odd(sp, 10),"Odd");
Thread even = new Thread(new Even(sp, 10),"Even");
odd.start();
even.start();
}
参考:here