【问题标题】:Main thread is blocked when calling method from another thread从另一个线程调用方法时主线程被阻塞
【发布时间】:2018-04-25 14:29:40
【问题描述】:

我正在尝试使用自定义对象创建一个新线程,然后从主线程调用此自定义对象方法。这个想法是主线程可以继续做其他事情,而自定义对象继续在第二个线程中工作:

public class Multithreading {
    public static void main(String[] args) {

        Multithreading mt = new Multithreading();
        mt.multiTest();
    }

    public void multiTest() {
        SomeObject someObject = new SomeObject();
        Thread thread = new Thread(someObject);
        thread.setDaemon(true);
        thread.start();
        someObject.startit();
        int i = 0;
        while (i < 3) { 
            try {

                System.out.println("this is the main thread being busy");

                Thread.sleep(3000);
                i += 1;
            } catch (InterruptedException e) {
            }

        }
    }

    class SomeObject implements Runnable {

        public void sayHello() {
            System.out.println("this is the second thread being busy");
        }

        public void startit() {
            int i = 0;
            while (i < 3) {
                try {
                    sayHello();

                    Thread.sleep(3000);
                    i += 1;
                } catch (InterruptedException e) {
                }
            }

        }

        @Override
        public void run() {
            // TODO Auto-generated method stub

        }
    }
}

输出是:

this is the second thread being busy
this is the second thread being busy
this is the second thread being busy
this is the main thread being busy
this is the main thread being busy
this is the main thread being busy

应该更像这样:

this is the second thread being busy
this is the main thread being busy
this is the second thread being busy
this is the main thread being busy
this is the second thread being busy
this is the main thread being busy

所以主线程被阻塞,直到方法完成。主线程是否在第二个线程中等待 someObject.startit() 的完成(作为返回类型为 void,我认为情况并非如此)?还是在第一个线程中执行,因此阻塞了它?

我知道使用下面的代码我可以在另一个线程中执行someObject.startit(),但它每次都会从头开始创建,我无法承受线程创建开销:

new Thread(() -> {someObject.startit();}).start(); 

一个线程如何在不阻塞的情况下调用另一个线程中的对象的方法?

【问题讨论】:

  • 每次需要运行一个单独的线程时,都需要创建一个新的线程对象。没有办法避免这种开销。您不能重用线程对象。最重要的是,您似乎有一个误解,即一旦将对象放入线程并启动线程,该对象中的任何操作都由该线程运行。这不是真的。

标签: java multithreading


【解决方案1】:

是主线程在等待someObject.startit()的完成吗 第二个线程(作为返回类型为 void,我认为这 不会是这样)?还是在第一个线程中执行, 因此阻止它?

直接在multiTest中调用someObject.startit()时,会在第一个调用线程中执行。

了解Runnbale不是Thread是非常重要的,Runnbale只是普通对象,除了它的run方法会在你创建并启动一个新对象时执行Thread 用它,像这样:

new Thread(new Runnable()).start;

所以,实际上,在这种情况下,线程阻塞与此无关。可以将startit()移动到run方法中,这样会被第二个线程执行:

@Override
public void run() {
    startit();
}

并且,为了避免线程创建开销,您可以使用线程池来执行它:

ExecutorService executorService = Executors.newCachedThreadPool(); // It should a singlton
// ExecutorService executorService = Executors.newFixedThreadPool(threadSize);
executorService.execute(() -> {
    someObject.startit();
});

【讨论】:

  • 我明白了。它在主线程中运行是有道理的,因为该线程调用了它。 run() 的问题是,我想在另一个线程中从一个对象执行不同的方法,具体取决于我目前需要的方法。使用run() 这是不可能的,因为方法被硬编码到对象中并且每次都是一样的。
  • @harbun 如果要避免线程创建开销,可以使用线程池。查看我的更新。
【解决方案2】:

另一个中执行的是Runnable对象的run方法。在您的情况下, run 方法是空的,因此在另一个线程中什么也不做。然后你调用 startit() 但从主线程,所以它在主线程中执行。这就是你得到这个结果的原因。

尝试将startit() 的主体放入run

【讨论】:

    【解决方案3】:

    someObject.startit(); 正在按顺序运行,而不是在您创建的线程上运行。

    要使其正常工作,您需要在 SomeObject 类的 run() 方法中调用 startit(); 方法

    【讨论】:

      【解决方案4】:

      你应该在run方法中调用你的函数,因为它是真正实现多线程的方法。

      【讨论】:

        【解决方案5】:

        如果我理解正确,您想创建一个新线程,然后命令该线程进行一些计算,而不是每次都创建一个新线程。

        我建议您使用ExecutorService class。它可用于管理一组线程,这些线程将接受新的并发工作,而无需每次调用​​方法时都创建新线程的开销。

        使用以下命令初始化服务:

         ExecutorService pool = Executors.newFixedThreadPool(poolSize);
        

        然后在池调用pool.execute(Runnable) 中的一个线程中运行一个方法。在此示例中,我将在 someobject 上使用您的 startit 方法。如果池中有可用的线程,它将在该线程中运行,否则将被放入队列中等待线程可用。

         pool.execute(someObject::startit);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-03-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-21
          • 2015-07-06
          • 2013-11-16
          • 1970-01-01
          相关资源
          最近更新 更多