【问题标题】:in java do thread local cached memory get flushed to main memory when destroyed ???在java中,线程本地缓存内存在销毁时是否会刷新到主内存???
【发布时间】:2016-07-04 06:37:00
【问题描述】:

我正在尝试设计一个使用 Executors.newSingleThreadExecutor() 制作的工作线程的 android 应用程序

但是我只希望该工作线程处理主线程发送的连续任务,同时保存属于该工作线程的一些信息。 (主线程不需要知道,只是工作线程应该在内部保留该信息。

// State saver class , once made by main thread only accessed by worker thread

public class StateSaver{

    public int count;

}

// Runnable obj that will be sent to worker thread from main thread
public class rnbl implements Runnable{

    final public StateSaver sv;

    public rnbl(StateSaver sv){
        this.sv = sv;
    }

    @Override
    public void run(){
        sv.count++;
    }
}

// Main Thread

ExecutorService ex = Executors.newSingleThreadExecutor();

StateSaver sv = new StateSaver();

public void functionCalledByMainThread(){



    ex.submit(new rnbl(sv));

}

但是问题是我发现当 newSingleThreadExecutor 长时间处于空闲状态时,它可能会破坏它创建的线程并在需要时用新线程替换它。

所以我担心的是,如果出现以下情况怎么办? :

  1. 工作线程更新了状态变量

  2. 变量已在线程缓存内存中更新,但尚未应用于主内存(该变量不应为易失性)

  3. 工作线程被销毁

  4. 更新永远不会应用于主内存...

那么如果执行器创建一个新线程继续执行任务,保存的状态可能不正确对吧?当然使用 volatile 这应该很容易,但我不需要使用 volatile

或者保证当一个线程被销毁时,它对变量所做的所有更改都会刷新到主内存中?

【问题讨论】:

  • 为什么不用volatile
  • 其实我只是有点好奇......也许我应该至少使用一个易失性变量将缓存刷新到主内存

标签: java android multithreading


【解决方案1】:

如果您想确保一个线程所做的更改随后终止对另一个线程可见,那么您可以使用Thread.join()。这为您提供了有保证的 happens-before 关系。

例如:

 Thread t = new Thread(new SomeRunnable());
 t.start();
 // do stuff
 t.join();
 // After the 'join', all memory writes made by Thread t are 
 // guaranteed to be visible to the current thread.

但您实际上是在询问ExecutorService,其中线程将无法供您“加入”。

以下内存一致性保证适用于ExecutorService

在将RunnableCallable 任务提交给ExecutorService 之前线程中的操作发生之前该任务采取的任何操作,然后发生-在之前通过Future.get()检索结果。

因此,获得所需一致性的方法是在任务的Future 上调用get()

【讨论】:

  • 谢谢,我想我现在应该学习一下 Future ,我以前从未使用过它
【解决方案2】:

ExecutorService 只有在 'run()' 方法完成后才能移除线程。只需实现线程生命周期的自定义协议(在等待和处理消息时存活或刷新状态并为特殊消息而死):

class App {
    static final String KILLER_MSG = "KILLER";
    public static void main(String[] args) {
        BlockingQueue<String> tasks = new ArrayBlockingQueue<String>(256);
        ExecutorService pool = Executors.newCachedThreadPool();

        // master / task producer
        pool.submit(() -> {
            tasks.add("task-0");
            tasks.add("task-1");
            tasks.add("task-2");
            tasks.add(KILLER_MSG);
        });

        // slave / task consumer / worker
        pool.submit(() -> {
            while (true) {
                String task = tasks.take();
                if (KILLER_MSG.equals(task)) {
                    // flush state here
                    break; // and die
                } else {
                    // process 'task' here
                    System.out.println("TASK: " + task);
                }
            }
        });
    }
}

【讨论】:

    猜你喜欢
    • 2014-04-10
    • 2016-05-07
    • 2011-01-30
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 2017-07-29
    • 2014-03-27
    • 1970-01-01
    相关资源
    最近更新 更多