基本上,我正在尝试实现一种机制,我有两个并行的线程。 Thread1不断更新计数器值。当计数器值达到特定值的增量(例如100,250,500的倍数)时,我希望Thread2并行执行在计数器值上选择的特定任务。 Thread1应该继续计数但是如果Thread2没有完成它的'它应该不计数超过键值。任务。
用例:线程1已将计数器更新为100.这将调度Thread2以执行TaskA。 Thread1仍然在计算。计数器达到250.如果Thread2已经完成了它的'任务,Thread1应该继续。否则,Thread1应该在继续之前等待TaskA完成。
|t2 |t1
| |
| |
| |
______100________ <----start thread 2 real quick
| |
| |
| |
| |
| |
| |
_______250______ <------at this point just wait for taskA to finish
| | IF it's not finished. If it is, start taskB and
| | continue counting
V V
我已经解决了这个问题,但到目前为止我已经取消了所有内容。我很欣赏代码/伪代码/提示/建议。提前致谢
答案 0 :(得分:2)
CyclicBarrier可用于创建一个屏障,其中线程将等待另一个线程。因此,下面有两个线程'countingThread'和'taskThread'。 'countingThread'将执行计数,并在计数到达特定点时调用'await',(下面是method-'checkBarrierCondition')。
根据问题中的示例,当计数线程达到100时,它可以在屏障上调用'await',如果任务线程在此时间内完成了任务,屏障将会捕捉并且两者都将继续到下一个活动。如果任务尚未完成,则计数器线程将等待执行任务的线程。
所有锁定都由CyclicBarrier和并发框架
处理public class Threading {
public void execute() {
final CyclicBarrier barrier = new CyclicBarrier(2);
Thread countingThread = new Thread(new Tasker(barrier));
Thread taskThread = new Thread(new Counter(barrier));
countingThread.start();
taskThread.start();
try {
countingThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Threading().execute();
}
class Tasker implements Runnable {
private CyclicBarrier barrier;
Tasker(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
String task = "taskA"; //just some mock-up task name
while (!allTasksDone(task)) {
task = performTask(task);
try {
System.out.println("Tasker : Await on barrier ");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
class Counter implements Runnable {
private CyclicBarrier barrier;
Counter(CyclicBarrier barrier) {
this.barrier = barrier;
}
public void run() {
int counter = 0; //just for the sake of example; starting at 0
while (!isCountingDone(counter)) {
counter = performCounting(counter);
if (checkBarrierCondition(counter)) {
try {
System.out.println("Counter : Await on barrier ");
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
}
}
答案 1 :(得分:0)
import java.util.concurrent.locks.Lock;
public class ThreadOne extends Thread {
private ThreadTwo two;
private Lock lock;
public ThreadOne(Lock l, ThreadTwo two) {
this.two = two;
this.lock = l;
this.start();
}
@Override
public void run() {
int i = 0;
while(true) {
if(i%100==0) {
// tell other thread to start
two.startRunning();
while(two.pending()) {
// wait until it actually started
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// acquire the lock (or wait)
lock.lock();
try {
// count up
i++;
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
执行线程:
import java.util.concurrent.locks.Lock;
public class ThreadTwo extends Thread {
private boolean pending = false;
private Lock lock;
public ThreadTwo(Lock l) {
this.lock = l;
this.start();
}
public void startRunning() {
pending = true;
}
public boolean pending() {
return pending;
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(200);
} catch (Exception e) {
}
if(pending) {
lock.lock();
try {
pending = false;
execute();
} catch (Exception e) {
} finally {
lock.unlock();
}
}
}
}
private void execute() {
}
}
以及如何启动它们。
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Main {
public static void main(String[] args) {
Lock l = new ReentrantLock();
ThreadTwo two = new ThreadTwo(l);
ThreadOne one = new ThreadOne(l,two);
}
}
答案 2 :(得分:0)
package testRandomStuff;
public class ThreadingPuzzle {
public int countMax = 25;
public int factor = 5;
public Thread threadA, threadB;
private class Signal {
public volatile boolean flag = true;
public Signal(boolean initial) {
flag = initial;
}
public synchronized void setFlag() {
flag = true;
notifyAll();
}
public synchronized void unsetFlag() {
flag = false;
notifyAll();
}
public synchronized boolean getFlag() {
return flag;
}
}
public Signal checkpoint = new Signal(true);
public Signal doWork = new Signal(false);
Runnable threadARunnable = new Runnable() {
@Override
public void run() {
for (int i = 0; i < countMax; i++) {
if (i % factor == 0) {
if (checkpoint != null) {
// --------mechanism to wait for threadB to finish---------
synchronized (checkpoint) {
try {
// -----use while loop to prevent spurious wakeup------
// Checkpoint flag is true in the first iteration, no need to wait.
while (!checkpoint.getFlag()) {
checkpoint.wait();
}
} catch (InterruptedException ie) {
// handle exception
}
}
// ThreadB has finished last job when threadA leaves the above sync-block
}
// ------ start threadB real quick---------
// unset checkpoint flag, so that threadA will not proceed the next
// interation without threadB setting the flag first.
// send signal to threadB to wake it up
checkpoint.unsetFlag();
doWork.setFlag();
}
System.out.println("Thread A - count:"+i);
}
}
};
Runnable threadBRunnable = new Runnable() {
@Override
public void run() {
while (true) {
// --------mechanism to wait for threadA send job---------
synchronized (doWork) {
try {
// -----use while loop to prevent spurious wakeup------
// doWork flag is false in the first iteration, wait for ThreadA.
while (!doWork.getFlag()) {
doWork.wait();
}
} catch (InterruptedException ie) {
// handle exception
}
}
doWork.unsetFlag();
// -----------do what ever you need to do in threadB-----------
System.out.println("Thread B - do some work");
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
}
System.out.println("Thread B - done working");
// ------------Finish work, notify threadA---------
checkpoint.setFlag();
}
}
};
public ThreadingPuzzle() {
// FIXME Auto-generated constructor stub
}
public static void main(String[] args){
ThreadingPuzzle puzzle = new ThreadingPuzzle();
puzzle.threadA = new Thread(puzzle.threadARunnable);
puzzle.threadB = new Thread(puzzle.threadBRunnable);
puzzle.threadA.start();
puzzle.threadB.start();
}
}
SIMULATION RESULTS
Thread B - do some work
Thread A - count:0
Thread A - count:1
Thread A - count:2
Thread A - count:3
Thread A - count:4
Thread B - done working
Thread B - do some work
Thread A - count:5
Thread A - count:6
Thread A - count:7
Thread A - count:8
Thread A - count:9
Thread B - done working
Thread B - do some work
Thread A - count:10
Thread A - count:11
Thread A - count:12
Thread A - count:13
Thread A - count:14
Thread B - done working
Thread B - do some work
Thread A - count:15
Thread A - count:16
Thread A - count:17
Thread A - count:18
Thread A - count:19
Thread B - done working
Thread B - do some work
Thread A - count:20
Thread A - count:21
Thread A - count:22
Thread A - count:23
Thread A - count:24
Thread B - done working
Thread B - do some work
Thread B - done working
答案 3 :(得分:0)
我建议看看Java的执行程序服务。它确实抽象了与多线程相关的大多数复杂性。此外,如果将来需要,您可以轻松增加执行任务的线程数。基本上你在第一个线程中运行计数。当您想在另一个线程中执行任务时,您只需创建一个可调用的。 API将为您的可调用者返回未来。在thread1中完成处理/计数后,只需从thread1调用get或getValue即可。现在它的美妙之处在于,如果其他线程已完成处理,它将立即返回结果。如果其他线程忙于处理任务,那么它将阻塞你的thread1,直到返回结果。请注意,您不需要手动执行任何锁定,阻止或通知。如果要在多个线程之间共享数据,请不要忘记使用线程安全集合。希望这有帮助!