- start() && run() 源码
- 区别
- Demo及Demo遇到的问题 (Method Reference)
Thread
Source Code
Thread start()
1 | /** |
Thread run()
1 | /** |
Diff
start() 方法是真正的启动方法,是并行调用的
run()是Thread中的一个方法,是串行调用的
Demo
1 | public class ThreadTest { |
Demo Encountered Problem
If Thread Start Twice
根据
Thread start()
源码可知,状态异常会抛出IllegalThreadStateException()异常1
2
3
4
5
6
7
8Thread startThread2 = new Thread(new MyRunnable());
startThread2.start();
System.out.println("start-2");
startThread2.start();
System.out.println("start-2 Again");
//if (threadStatus != 0)
// throw new IllegalThreadStateException();
Method Reference Problem
使用方法引用启动的线程不论是run()还是start()方法都不会真正调用
1
2
3
4Thread noPrintRunThread = new Thread(MyRunnable::new);
noPrintRunThread.run();
noPrintRunThread.start();
System.out.println("No Print End");ChatGPT回答
1
2
3
4
5Regarding your question, when you use a method reference like MyRunnable::new, you're actually referencing a constructor method of the MyRunnable class. When you call the constructor with arguments like new MyRunnable("myRunnable start()"), you're invoking a specific constructor method that takes a string argument.
In the case of new Thread(MyRunnable::new).start(), the Thread constructor that takes a Runnable argument is being invoked. The MyRunnable::new method reference is a reference to the constructor method that takes no arguments. Therefore, when the Thread object is created and started, the run() method of the MyRunnable object that was created with no arguments is executed.
To make the code work as you intended, you need to provide a constructor method reference that takes a string argument, like new MyRunnable("MyRunnable with argument")::new. This will create a reference to the constructor method that takes a string argument, and when the Thread object is created and started, the run() method of the MyRunnable object that was created with the string argument is executed.求证
new 与 Object::new
通过 java - Runnable::new vs new Runnable() - Stack Overflow ,可知Object::new方法是创建一个实例,并不会调用内部的run方法。即如果内部有两个Runnable,之后执行最上层的那个。
通过构造器引用和直接用new创建对象区别 - lonecloud - 博客园 (cnblogs.com) 字节码查看,方法引用并没有调用init()方法,因此实际上没有真正产生对象
推断:类似于Spring三级缓存,方法引用实际上只是一个lambda表达式,还没到真正创建对象的状态,没有传入其他参数,不需要进入set属性方法,因此使用
Myrunnable::new
方法并不会生成内部属性,因而没有执行run()方法。若理解错误请帮忙指出,谢谢
为什么 MyRunnable::new不生效
由于只是创建出构造函数的实例,没有真正生成对象,导致内部产生两个Runnable,只会执行最外层方法,无法调用内部run()方法,因此不生效
结论
对于线程创建,不能使用方法引用,只能通过其余方法启动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public void threadTest() throws InterruptedException {
// method reference,not working
CountDownLatch latch = new CountDownLatch(4);
new Thread(MyRunnable::new,"method reference").start();
//worked
new Thread(new MyRunnable("Another Method Reference", latch)::run).start();
//worked
MyRunnable myRunnable = new MyRunnable("myRunnable start()", latch);
new Thread(myRunnable).start();
//worked
new Thread(() -> new MyRunnable("MyRunnable.run() start()", latch).run()).start();
//worked
new Thread(new MyRunnable("MyRunnable.start()", latch)).start();
latch.await();
System.out.println("All Thread Done.");
}
Source
- Thread (Java Platform SE 7 ) (oracle.com)
- Java8中直接new对象和用 类名::new 创建对象这两种形式有什么区别_王人冉的博客-CSDN博客_jdk8 new撖寡情
- Thread使用start和run方法启动线程有什么区别?_胖子爱你520的博客-CSDN博客_thread start
- 【java】Thread.start 它是怎么让线程启动的呢_九师兄的博客-CSDN博客_java thread start
- java - Runnable::new vs new Runnable() - Stack Overflow
- 构造器引用和直接用new创建对象区别 - lonecloud - 博客园 (cnblogs.com)