问题 主方法关闭后如何运行线程?


这是我的两个班级:

public class Firstclass {
    public static void main(String args[]) throws InterruptedException {
        System.out.println("Main start....");
        Secondclass t1 = new Secondclass();
        t1.setName("First Thread");
        Secondclass t2 = new Secondclass();
        t2.setName("Second Thread");
        t1.start();
        t2.start();
        System.out.println("Main close...");
    }
}

public class Secondclass extends Thread {
    @Override
    public void run() {
        try {
            loop();
        } catch(Exception e) {
            System.out.println("exception is" + e);
        }
    }

    public void loop() throws InterruptedException {
        for(int i = 0; i <= 10; i++) {
            Thread t = Thread.currentThread();
            String threadname = t.getName();
            if(threadname.equals("First Thread")) {
                Thread.sleep(1000);
            } else {
                Thread.sleep(1500);
            }
            System.out.println("i==" + i);   
        }
    }
}

现在我跑的时候 Firstclass 然后输出是:

Main start....
Main close...
i==0
i==0
i==1
i==1
i==2
i==3
i==2
i==4
i==3
i==5
i==6
i==4
i==7
i==5
i==8
i==9
i==6
i==10
i==7
i==8
i==9
i==10

我的第一个问题是: 我想知道为什么两个线程仍在运行,即使它 main 方法已经完成?

我的第二个问题是: 任何人都可以向我解释方法之间的区别 join 和 synchronized


4200
2018-03-03 12:31


起源

如果要在main方法完成时退出,请创建线程守护程序 - Vinayak Pahalwan


答案:


你的 main 线程未关闭 -

      // ...
      System.out.println("Main close...");
      // <--- Your main method is here while all the other threads complete (sort of).
     }

在你的问题的第2部分 - 之间没有联系 join 和 synchronized。它们几乎相反。

  • join  - 等待线程完成后再恢复。
  • synchronized  - 只有一个线程可以进入此处,其他线程必须等待。

1
2018-03-03 12:38



@Sivaranjani D在这里说相反。告诉我他怎么了? - TruePS
-1。方法 main 将 不 等到所有线程都完成,除非你明确使用 join。在完成所有用户线程之前,JVM不会结束该过程。 - Snps
@snps - 给我 在所有用户线程完成之前,JVM不会结束该过程 相当于最后的隐式连接 main。我接受有一个微妙的区别,但你确定它值得一个downvote吗? - OldCurmudgeon
@TruePS - 因为 main  方法 主要叫做 线。该 main  方法 完成但是 main  线 将等到它创建的所有其他非守护程序线程在退出VM之前都已停止。 - OldCurmudgeon
@TruePS由于Java是一种托管语言,所有二进制代码都在上面执行 Java虚拟机 它跟踪当前正在运行的线程以及哪些是守护程序线程等。从主线程生成的线程不被视为主线程的“子”,而是作为JVM监视的单独线程执行。主线程完全可以在其他线程仍在运行时终止,然后JVM将在退出之前等待所有非守护程序线程完成。 - Snps


我想知道即使主要方法是关闭的,两者都是如何   线程还在运行?

一旦最后一个非jvm线程终止,JVM将退出。这意味着如果您创建的任何线程仍在运行,则jvm将不会关闭。守护程序线程是不阻止JVM关闭的线程。通常你会将它们用于某些后台任务,如果用户要求它关闭,你不希望保持你的应用程序。

守护程序线程是一个线程,当程序完成但线程仍在运行时,它不会阻止JVM退出。守护程序线程的一个示例是垃圾收集。

你可以使用 setDaemon() 更改Thread守护程序属性的方法。默认情况下,除非您明确调用,否则用户创建的每个线程都是普通(非守护程序)线程 setDaemon() 方法。

解释一下join方法和join有什么区别   同步

同步 是一种锁定机制,允许两个线程不相互踩,即 同步 用于在锁定机制的帮助下通过多个线程提供对共享资源的适当访问。
另一方面 join() 方法调用允许一个线程等待另一个线程的完成。


3
2018-03-03 12:36



所以你说主线程在线程t1和t2完成后死亡。 - TruePS
我说JVM进程不会终止,直到t1和t2完成。主要方法将会消失。您可以通过调用join方法使其等待t1和t2。 - Ankur Shanbhag


你的第一个问题,

默认情况下调用main方法时会创建一个主线程。主线程是非dameon线程。当main方法创建的线程继承它的parant属性时。这意味着它们都是非守护程序线程。如您所知,JVM等待所有非守护程序线程完成。所以它甚至会在主线程完成后执行。

看这里 : 守护进程与非守护进程 每个线程创建的Java堆栈

和你的第二个问题: join方法在调用join方法的线程末尾加入当前运行的线程。这意味着当前线程将被停止,并在join方法引用的线程之后启动。

同步会停止两个线程同时执行相同的代码。


3
2018-03-03 12:47



现在我正式感到困惑,因为其他人已回答主线程在每个其他线程死亡后死亡,并且您说主方法已死并且其他线程仍在执行。 - TruePS
主线程不会等到所有它的子线程完成。看我的帖子 technicalminds.in/core-java/... 用示例证明。 - Sivaranjani D


我想知道即使主要方法是关闭的,两者都是如何   线程还在运行?

你的 main() 方法由一个单独的线程运行,该线程启动另外两个线程(First 广告 Second)。所有线程不相互依赖,因此,主线程可以打印其他线程起始行下面的行。

我的第二个问题是任何人都可以解释我有什么区别   在join方法和synchronized之间?

join() 意味着等待线程完成。这是一种阻止方法。 synchronized是一个关键字,表示多线程无法同步访问同步块/方法。


2
2018-03-03 12:34



@Kugathasan我不明白你的回答请告诉我主要方法()在上述程序的情况下何时会死? - TruePS


加入 如果你有一个线程B在另一个线程A完成其工作之前无法完成其工作,那么你希望线程B“加入”线程A.

同步 当我们使用线程时,我们通常需要在某处使用某些同步 确保我们的方法不会在错误的时间互相打断并弄乱我们的方法 数据。通常,任何时候多个线程访问可变(可更改) 数据,您同步以保护该数据,以确保两个线程不会更改 它同时(或者一个没有同时改变另一个) 阅读它,这也令人困惑)。


2
2018-03-03 12:39



希望这个问题可以帮助你清除你的困惑: stackoverflow.com/questions/8784333/... - Saurabh Jain


用户和守护程序有两种类型的线程。因此,如果您希望程序退出,请将您的线程作为守护程序。

Thread t = new Thread();
t.setDaemon(true);

当没有更多用户线程时,该进程终止。

至于你的第二个问题:

加入 只有在需要确保线程死亡且之后无所事事时才使用

同步 用于线程间通信


2
2018-03-03 12:42



你说如果我使用我的线程守护进程然后main方法()死了,在上面的例子中,所有方法都是用户方法所以什么时候主方法会死? - TruePS