Java 如何同时启动两个线程(或在关闭时启动)

Java 如何同时启动两个线程(或在关闭时启动),java,multithreading,Java,Multithreading,我有一个班级笔记和一个班级会议。类Note中有一个名为noteList的ArrayList。创建会议的对象后,该对象将被注册到备注列表中 我只想在main类中演示,可以同时(或同时)创建会议的两个对象。我的计划是: public class Note{ //some field and method hier public void add(Meeting m){ notes.add(m); } private static final List

我有一个班级
笔记
和一个班级
会议
。类
Note
中有一个名为
noteList
ArrayList
。创建
会议
的对象后,该对象将被注册到
备注列表

我只想在main类中演示,可以同时(或同时)创建
会议的两个对象。我的计划是:

public class Note{
    //some field and method hier
    public void add(Meeting m){
        notes.add(m);
    }
    private  static final List<Entry> notes =
        Collections.synchronizedList(new ArrayList<Entry>());
}

public class Meeting implements Runnable{
    public Meeting(Note note_1,Note note_2,Calendar calendar){
        note_1.add(this);
        note_2.add(this);}
        //some method
    }

    public class Test implements Runnable{
        public static void main(String[] args) {
            Note note_1 = new Note();                
            Note note_2 = new Note();
            Meeting m_1 = new Meeting(note_1,note_2);
            Meeting m_2 = new Meeting(note_2,note_1)
            Thread t1 = new Thread(m_1);
            Thread t2 = new Thread(m_2)
            t1.start();
            t2.start();
        }
        //t1,t2 are two thread and they start one to one(not at the same time).
公共课堂笔记{
//一些领域和方法
公开会议(会议m){
注:增加(m);
}
私人静态最终清单注释=
Collections.synchronizedList(新的ArrayList());
}
公共类会议实现Runnable{
公开会议(注1、注2、日历){
注1.添加(本);
注2.添加(此);}
//某种方法
}
公共类测试实现可运行{
公共静态void main(字符串[]args){
注1=新注();
注2=新注();
会议m_1=新会议(注1、注2);
会议m_2=新会议(注2,注1)
螺纹t1=新螺纹(m_1);
螺纹t2=新螺纹(m_2)
t1.start();
t2.start();
}
//t1、t2是两个线程,它们以一对一的形式开始(不是同时开始)。

我在任何地方都读过,可以使用
wait()
notify()
notifyAll()
,但它们必须在同步的方法中使用。我的程序中没有同步的方法。

这是启动两个线程的关键

要使运行方法更加同步,您可以让它们在运行方法的顶部等待

这样做可以减少创建和启动线程的开销(执行run方法之前发生的部分),也可以减少一些奇怪的调度问题。但是,您无法保证闩锁后的代码实际执行的并发程度

CountDownLatch latch = new CountDownLatch(2);

Runnable r1 = new Meeting(latch);
Runnable r2 = new Meeting(latch);


// in Meeting

private final CountDownLatch latch;

public void run(){

   latch.countDown();
   latch.await();

   // other code
}

不幸的是,无法同时启动两个线程

让我更好地解释一下:首先,序列
t1.Start();
t2.Start()
首先使用t1执行,然后使用t2执行。这意味着只有线程t1被安排在线程2之前,而不是实际启动。这两个方法每一个都需要秒的分数,因此人类观察者无法看到它们顺序的事实

此外,Java线程是调度的,即分配给最终执行的。即使您有一个多核CPU,您也不能确定1)线程是并行运行的(其他系统进程可能会干扰),2)线程都是在调用
start()
方法之后启动的。

它们是从同时“关闭”。关键是您的代码没有在
t1.start()
处阻塞

您可以通过在
Meeting
类的
run()
方法的顶部添加一条print语句,并在
t2.start()之后添加另一条print语句来看到这一点

public class Meeting implements Runnable {
    private String name;
    public Meeting(String name) {
        this.name = name;
    }
    public void run() {
        System.out.println(name + " is running");
    }
}

public class Test {
    public static void main(String[] args) {
        Meeting m_1 = new Meeting("meeting 1");
        Meeting m_2 = new Meeting("meeting 2")
        Thread t1 = new Thread(m_1);
        Thread t2 = new Thread(m_2)
        t1.start();
        t2.start();
        System.out.println("this might print first!");
    }
}

// possible output:
> this might print first!
> meeting 1 is running
> meeting 2 is running

您不能同时启动两个线程,但可以在run方法中进行同步。当然,您所说的关于最终执行的所有内容仍然适用。但至少您可以协调run方法的执行顺序,以防存在一些相互依赖性。当您处理线程和/或多个CPU时,确实存在no例如“同时”。你需要澄清你的问题。在你编写的代码中,
m_1
总是被创建(实例化)在
m_2
之前,虽然它们都将同时存在于内存中,直到GC决定清理它们。你是指其他什么吗?在任何情况下,如果你搜索为什么单例的双重检查锁定不起作用,你会对Java中的同步问题有一个很好的概述。我认为缺少了一个。我的意思是m_1和m_2怎么可能您正在使用同步方法,因为synchronizedList()返回一个已同步其所有方法的列表。我使用synchronizedList来ArrayList notes的原因是,在类notes中,我希望每5分钟在notes中输出元素。我有一个run()课堂笔记。我无法粘贴run()hier,我将把它添加到问题中。@echo欢迎加入社区。我查看了问题的编辑日志,注意到您在原始帖子中添加了整个第二个问题。如果您有两个问题(或得出第二个后续问题)这在本质上是不同的,你应该强烈地考虑把它们作为两个问题来张贴。你只能保证一个线程没有等到第二个到达倒计时。这确保了它们都是启动的,但是一个可以马上停止运行。@ Peter Lawrey:是的,这就是我的意思。但是,您无法保证闩锁后的代码实际执行的并发程度”。如果您愿意,您可以强制执行的只是严格的顺序。+1用于显示一个很可能导致并发执行的方法(多次重复)。请注意,
CyclicBarrier
在这种情况下也可以工作。