【问题标题】:Thread Questions - java.util.concurrent - Runnable/Callable线程问题 - java.util.concurrent - Runnable/Callable
【发布时间】:2012-03-15 13:33:55
【问题描述】:

好的,我承认我是 Java 线程的新手,我一直在阅读有关 java.util.concurrent 的大量内容,并且有一些问题希望真人能够回答。

首先,我创建了 ThreadPoolExecutor 和 BlockQueue 来帮助运行我的 Runnable/Callable 方法。为了使事情变得简单,我的知识有限,我将所有活动限制为只读,没有修改传递给 Runnable 的对象,并且创建的信息是从数据库中提取的,应用程序使用它来填充 GUI 表,任何信息都在数据库可以在接收之前或之后进行更改,这与显示目的无关。

我很好奇的是我所做的是否是线程安全的。我已经扩展了 ThreadPoolExecutor,所以我可以重写 afterExecute 方法以在 Runnable 完成线程中的工作后执行它。从我的阅读来看,这个操作似乎是在主线程中完成的,并且被认为是线程安全的。

同样继续这个想法,如果我在这个 Runnable/Callable 类中编写另一个方法并直接使用它而不使用它也将在主线程上运行的 run(或 ThreadPoolExecutor.execute())注意安全。问题二:如果我从 Runnable 类的 run() 方法中使用这个方法,它是在线程上运行的吗? (我假设是,并要求确认)如果我直接运行这个方法,它会在主线程上运行吗?

原因是因为我希望将与查询/更新/插入有关的所有内容保留在一个类中,但在主线程中保留对数据库的更新。

一些代码帮助解释:

扩展的ThreadPoolExecutor:

public class DatabaseThreadPoolExecutor extends ThreadPoolExecutor {
    public DatabaseThreadPool(int corePoolSize, int maximumPoolSize, long keepAlive, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        super(//pass info to super)
    }

    protected void afterExecute(Runnable runnable, Throwable throwable) {
        if(runnable instanceof someRunnable) {
            ((SomeRunnable) runnable).afterExecution();
        }
    }
}

Runnable 类:

public class someRunable implements Runable {

    public someRunnable() {
        // used code withing thread
    }

    public doAfterExecute() {
        // run by ThreadPoolExecutor .afterExecute()
    }

    public doSomething() {
        // Run by someRunnable in thread
        // Also run directly by some other class
    }
}

其他一些调用 doSomething() 的类:

public class someOtherClass {
    public SomeOtherClass(Runnable someRunnable) {
        someRunable.doSomething();
    }
}

【问题讨论】:

  • 你说的“主线程”是指Swing/AWT事件线程吗?
  • 用一点代码更容易回答。
  • 标题中的Callable是从哪里来的?
  • 打算使用 Callable 来返回未来,或者只是使用 runnable 来填充对象并在执行后使用数据......在这种情况下,Callable 和 Runnable 与 .afterExecute 相同...抱歉,我没有再次提及 Callable。

标签: java concurrency


【解决方案1】:

如果不查看所有代码,就无法说如此高级别的描述是“线程安全的”。据我们所知,您使用的架构中“读取”是一个阻塞操作,它会在您身上死锁!

通常可以将资源或类描述为“线程安全”,这意味着它在被多个线程使用时不会表现出不可预测的行为。但是,给定的资源是“线程安全”的,并不是证明当您尝试并行执行某些事情时不会导致任何错误,如果这一切都在一个线程上完成就不会发生。只是行为是可预测的(对于任何给定的时间集合,它们本身当然是不可预测的)。

“线程安全”也不表示某些东西实际上适合高并发使用。完全同步的 ArrayList 是“线程安全的”,但您当然不希望编写一个在许多经常使用它的线程之间共享它的程序!

虽然会尝试回答您的实际问题!:

首先我创建了 ThreadPoolExecutor 和 BlockQueue 来帮助运行我的 可运行/可调用方法。用我的有限来保持简单 knownledge 我已将所有活动限制为只读,没有对象通过 进入Runnable被修改

这似乎是一个明显错误的陈述。如果你的 runnable 做了任何事情,那么你正在阅读的东西一定是在某个地方。某处必须是可运行对象引用的东西。 您需要分析的是将读取结果推送到其中的资源如何响应并发访问。这就是潜在危险所在。

我已经扩展了 ThreadPoolExecutor,所以我可以覆盖 afterExecute 在 Runnable 完成后执行方法的方法 它在线程中的工作。根据我的阅读,这似乎 操作在主线程中完成,将被视为线程 安全。

不,afterExecute() 将在调用 runnable 上的 run() 方法的同一池线程中调用。不在提交 Runnable 的线程中。 "This method is invoked by the thread that executed the task"

同样继续这个想法,如果我写另一个方法是 也在这个 Runnable/Callable 类中,直接使用它 使用 run(或 ThreadPoolExecutor.execute()),它也会 在主线程上运行并确保安全。

是的,它将在您调用该方法的线程中运行,而不是在池线程中。 “安全”是我们无法仅从架构描述(以及一致同意的安全定义)中分辨出来的东西:)。

问题二:如果我从 Runnable 类是在线程上运行的吗? (我认为是,并要求 确认)

是的,您在 run() 方法中调用的任何内容都将由接收您的任务的池线程执行。

【讨论】:

  • 好吧,看来我的想法需要一些修改......也许需要一个指向一些好的阅读的链接,也许需要更好地描述我正在尝试做的事情。我需要在不暂停主应用程序的情况下从冗长的数据库调用中获取信息,无论如何服务器都不能进入睡眠状态,该信息需要返回到主应用程序。我发现的所有示例都等待锁定或同步对象并停止主代码。
  • 对不起,如果我一开始就过于悲观。你当然是正确地处理事情并朝着正确的方向前进。我可能对“线程安全”一词的高度可变定义有太多的个人不满。 (以及有时人们倾向于假设“线程安全架构”意味着“不会有单线程版本没有的由并发资源使用引起的错误。”)
  • 完全没问题。我有书籍和互联网可以使用,所以我的想法需要修正;)你是非常正确的并且已经回答了我的问题,但不幸的是已经打开了这么多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-04
相关资源
最近更新 更多