하는 방법 인터럽트는 BlockingQueue 는 차단을()?
-
03-07-2019 - |
문제
내가 있는 클래스에서 개체 BlockingQueue
과 프로세스들에 의해 호출 take()
하는 작업을 반복했습니다.어떤 시점에서 난 더 이상 물체에 추가될 것입니다.나는 어떻게 인터럽트 take()
방법을 중단이 막고 있는가?
여기에는 클래스 프로세스 개체:
public class MyObjHandler implements Runnable {
private final BlockingQueue<MyObj> queue;
public class MyObjHandler(BlockingQueue queue) {
this.queue = queue;
}
public void run() {
try {
while (true) {
MyObj obj = queue.take();
// process obj here
// ...
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
그리고 여기에는 방법을 사용하는 이 클래스는 프로세스 개체:
public void testHandler() {
BlockingQueue<MyObj> queue = new ArrayBlockingQueue<MyObj>(100);
MyObjectHandler handler = new MyObjectHandler(queue);
new Thread(handler).start();
// get objects for handler to process
for (Iterator<MyObj> i = getMyObjIterator(); i.hasNext(); ) {
queue.put(i.next());
}
// what code should go here to tell the handler
// to stop waiting for more objects?
}
해결책
스레드를 방해하는 것이 옵션이 아닌 경우, 다른 하나는 큐에 "마커"또는 "명령"객체를 MyObjhandler로 인식하고 루프에서 나누는 것입니다.
다른 팁
BlockingQueue<MyObj> queue = new ArrayBlockingQueue<MyObj>(100);
MyObjectHandler handler = new MyObjectHandler(queue);
Thread thread = new Thread(handler);
thread.start();
for (Iterator<MyObj> i = getMyObjIterator(); i.hasNext(); ) {
queue.put(i.next());
}
thread.interrupt();
그러나이 작업을 수행하면 대기열에 여전히 항목이있는 동안 스레드가 중단 될 수 있으며 처리되기를 기다리고 있습니다. 사용을 고려하고 싶을 수도 있습니다 poll
대신에 take
, 이는 처리 스레드가 타임 아웃을 허용하고 새로운 입력없이 잠시 기다렸을 때 종료 될 수 있습니다.
매우 늦었지만 희망이 다른로 내가 직면한 문제 및 이용 poll
접근 방식에 의해 제안 에릭슨의 위 으로 약간의 변화
class MyObjHandler implements Runnable
{
private final BlockingQueue<MyObj> queue;
public volatile boolean Finished; //VOLATILE GUARANTEES UPDATED VALUE VISIBLE TO ALL
public MyObjHandler(BlockingQueue queue)
{
this.queue = queue;
Finished = false;
}
@Override
public void run()
{
while (true)
{
try
{
MyObj obj = queue.poll(100, TimeUnit.MILLISECONDS);
if(obj!= null)//Checking if job is to be processed then processing it first and then checking for return
{
// process obj here
// ...
}
if(Finished && queue.isEmpty())
return;
}
catch (InterruptedException e)
{
return;
}
}
}
}
public void testHandler()
{
BlockingQueue<MyObj> queue = new ArrayBlockingQueue<MyObj>(100);
MyObjHandler handler = new MyObjHandler(queue);
new Thread(handler).start();
// get objects for handler to process
for (Iterator<MyObj> i = getMyObjIterator(); i.hasNext(); )
{
queue.put(i.next());
}
// what code should go here to tell the handler to stop waiting for more objects?
handler.Finished = true; //THIS TELLS HIM
//If you need you can wait for the termination otherwise remove join
myThread.join();
}
이는 해결 모두 문제
- 플래그
BlockingQueue
그래서 그것을 알고 있지 않기 위해 더 많은 요소 - 하지 않았다 사이에서 중단되도록 처리 블록을 종료한 경우에만 모든 항목에서 큐 처리하고 있는 남은 항목을 추가할
스레드를 방해합니다.
thread.interrupt()
또는 방해하지 마십시오.
public class MyQueue<T> extends ArrayBlockingQueue<T> {
private static final long serialVersionUID = 1L;
private boolean done = false;
public ParserQueue(int capacity) { super(capacity); }
public void done() { done = true; }
public boolean isDone() { return done; }
/**
* May return null if producer ends the production after consumer
* has entered the element-await state.
*/
public T take() throws InterruptedException {
T el;
while ((el = super.poll()) == null && !done) {
synchronized (this) {
wait();
}
}
return el;
}
}
- 프로듀서가 대기열에 객체를 넣으면 전화하십시오
queue.notify()
, 종료되면 전화하십시오queue.done()
- 루프 while (! queue.isdone () ||! queue.isempty ())
- null의 테스트 () 반환 값을 테스트합니다
제휴하지 않습니다 StackOverflow