Java 从另一个线程调用方法时,主线程被阻塞

Java 从另一个线程调用方法时,主线程被阻塞,java,multithreading,Java,Multithreading,我试图用一个自定义对象创建一个新线程,然后从主线程调用这个自定义对象方法。其思想是主线程可以继续执行其他任务,而自定义对象可以继续在第二个线程中工作: public class Multithreading { public static void main(String[] args) { Multithreading mt = new Multithreading(); mt.multiTest(); } public void m

我试图用一个自定义对象创建一个新线程,然后从主线程调用这个自定义对象方法。其思想是主线程可以继续执行其他任务,而自定义对象可以继续在第二个线程中工作:

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

        }
    }
}
@Override
public void run() {
    startit();
}
应该是这样的:

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
new Thread(new Runnable()).start;
因此,主线程被阻塞,直到方法完成。主线程是否在第二个线程中等待完成
someObject.startit()
(作为返回类型为void,我认为情况并非如此)?或者它是在第一个线程中执行的,因此阻塞了它

我知道,使用以下代码,我可以在另一个线程中执行
someObject.startit()
,但每次都会从头开始创建,我负担不起线程创建开销:

new Thread(() -> {someObject.startit();}).start(); 
一个线程如何从另一个线程中的对象调用方法而不阻塞?

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


要使其工作,您需要调用
startit()run()
SomeObject
类的
method中执行的是可运行对象的
run
方法。在您的例子中,run方法是空的,因此在另一个线程中没有执行任何操作。然后从主线程调用
startit()
,因此它在主线程中执行。这就是你得到这个结果的原因


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

中,您应该在run方法中调用您的函数,因为它实际上是实现多线程的方法

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

当您在
multiTest
中直接调用
someObject.startit()
时,它将在第一个调用线程中执行

了解
Runnbale
不是
Thread
非常重要,
Runnbale
只是普通对象,除了它的
run
方法将在您使用它创建和启动新的
Thread
时执行,如下所示:

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
new Thread(new Runnable()).start;
所以,实际上,在这种情况下,与线程阻塞无关。您可以将
startit()
移动到
run
方法,因此它将由第二个线程执行:

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

        }
    }
}
@Override
public void run() {
    startit();
}
而且,为了避免线程创建开销,您可以使用线程池来执行它:

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

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

我建议你用这个。它可以用来管理一组线程,这些线程将接受新的并发工作,而无需在每次调用方法时创建新线程

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

 ExecutorService pool = Executors.newFixedThreadPool(poolSize);
然后在池中的一个线程中运行方法,调用
pool.execute(Runnable)
。在本例中,我将在
someobject
上使用您的
startit
方法。如果池中有一个可用线程,它将在该线程中运行,否则它将被放在队列中等待线程变为可用

 pool.execute(someObject::startit);

每次需要运行单独的线程时,都需要创建一个新的线程对象。没有办法避免这种开销。不能重用线程对象。最重要的是,您似乎有一个误解,即一旦将对象放入线程并启动线程,该对象中的任何操作都将由该线程运行。相关人员:我明白了。它在主线程中运行是有意义的,因为该线程调用了它。
run()
的问题是,我想在另一个线程中从一个对象执行不同的方法,具体取决于我目前需要的方法。使用
run()
这是不可能的,因为方法是硬编码到对象中的,每次都是一样的。@harbun如果您想避免线程创建开销,可以使用线程池。查看我的更新。