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
在这种情况下也可以工作。