2016-07-26 4 views
0

실행 가능 서비스가 executor 서비스 (무제한 큐를 가지는 단일 thread)에 송신 된 후에 실행 가능한 객체를 변경할 수 있습니까? 예를 들어실행 가능 객체가 ExecutorService에 제출 된 후 실행 가능 객체를 수정 하시겠습니까?

:

우리가 실행 가능한 오브젝트를 제출하는 경우, 위의 예에서 볼 수 있으며 루프 내에서 너무 객체의 내용을 수정할 수 있듯이
public class Test { 
    @Autowired 
    private Runner userRunner; 

    @Autowired 
    private ExecutorService executorService; 

    public void init() { 
     for (int i = 0; i < 100; ++i) { 
      userRunner.add("Temp" + i); 
      Future runnerFuture = executorService.submit(userRunner); 
     } 
    } 
} 

public class Runner implements Runnable { 
    private List<String> users = new ArrayList<>(); 

    public void add(String user) { 
     users.add(user); 
    } 

    public void run() { 
     /* Something here to do with users*/ 
    } 
} 

, 1은 서비스가를 사용 집행하기 위해 제출 새로 추가 된 사용자. run 메소드가 매우 집중적 인 작업을 수행하고 후속 제출이 대기 중임을 고려하십시오.

답변

1

실행 가능한 객체를 제출하고 루프 내부에서 객체의 내용을 수정하면 1 차로 실행자 서비스에 제출 한 새로 추가 된 사용자가 사용됩니다.

usersArrayList이 올바르게 동기화 된 경우에만. 당신이하고있는 일은 예외와 다른 예측할 수없는 결과를 초래할 수있는 두 개의 다른 스레드에서 users 필드를 수정하려고 시도하는 것입니다. 동기화는 뮤텍스를 보장하므로 여러 스레드가 예기치 않게 동시에 변경하지 않으며 메모리 동기화를 통해 한 스레드의 수정 사항을 다른 스레드가 볼 수 있도록 보장합니다. 당신은 수동으로하면 동기화해야합니다, 그러나

// you can't use this if you are iterating on this list (for, etc.) 
private List<String> users = Collections.synchronizedList(new ArrayList<>()); 

:

public void add(String user) { 
    synchronized (users) { 
     users.add(user); 
    } 
} 
... 

public void run() { 
    synchronized (users) { 
     /* Something here to do with users*/ 
    } 
} 

또 다른 옵션 목록을 동기화하는 것입니다 : 당신은 무엇을 할 수 있는지

귀하의 예제에 동기화를 추가하는 것입니다 목록에 for 루프를 사용하거나 다른 방법으로 반복합니다.

0

가장 깨끗한 가장 직접적인 방법은 미래에 대한 취소를 호출 한 다음 업데이트 된 사용자 목록을 사용하여 새 작업을 제출하는 것입니다. 그렇지 않으면 목록 전체에 걸친 변경으로 인해 가시성 문제가 발생할뿐만 아니라 이미 실행중인 작업을 수정하고 있는지 여부를 알 수 없습니다.