相关文章
更多最近更新
更多关于Thread类中的start()方法和run()方法
2019-03-25 13:32|来源: 网路
引用
public void start()
Causes this thread to begin execution; the Java Virtual Machine calls the run method of this thread.
The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
Throws:
IllegalThreadStateException - if the thread was already started.
public void run()
If this thread was constructed using a separate Runnable run object, then that Runnable object's run method is called; otherwise, this method does nothing and returns.
Subclasses of Thread should override this method.
Specified by:
run in interface Runnable
上面是Thread类中Start()方法与run()方法的定义。
现有自定义的类如下:
public class Test2 { public static void main(String[] args) { Thread t1 = new Thread(new Runnable() { @Override public void run() { System.out.println("in runnable() run()."); } }); Thread t2 =new MyThread(); t1.start(); t2.start(); } static class MyThread extends Thread { @Override public void run() { System.out.println("in MyThread() run()."); } } }
由于t2并没有指定target,即没有这样定义
Thread t2 = new Thread(new MyThread());所以根据API中run()方法的定义,t2.start()方法的调用应该没有调用MyThread的run()方法。
Thread类的run() 源代码如下:
public void run() { if (target != null) { target.run(); } }
Thread类无参构造函数
public Thread() { init(null, null, "Thread-" + nextThreadNum(), 0); }
private void init(ThreadGroup g, Runnable target, String name, long stackSize) { Thread parent = currentThread(); SecurityManager security = System.getSecurityManager(); if (g == null) { /* Determine if it's an applet or not */ /* If there is a security manager, ask the security manager what to do. */ if (security != null) { g = security.getThreadGroup(); } /* If the security doesn't have a strong opinion of the matter use the parent thread group. */ if (g == null) { g = parent.getThreadGroup(); } } /* checkAccess regardless of whether or not threadgroup is explicitly passed in. */ g.checkAccess(); /* * Do we have the required permissions? */ if (security != null) { if (isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION); } } g.addUnstarted(); this.group = g; this.daemon = parent.isDaemon(); this.priority = parent.getPriority(); this.name = name.toCharArray(); if (security == null || isCCLOverridden(parent.getClass())) this.contextClassLoader = parent.getContextClassLoader(); else this.contextClassLoader = parent.contextClassLoader; this.inheritedAccessControlContext = AccessController.getContext(); this.target = target; setPriority(priority); if (parent.inheritableThreadLocals != null) this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals); /* Stash the specified stack size in case the VM cares */ this.stackSize = stackSize; /* Set thread ID */ tid = nextThreadID(); }
但是根据API中start()方法的说明,run()方法是由JVM调用的,这是不是矛盾了?
求解答,谢谢啦。
问题补充:首先,谢谢AngelAndAngel和chen_yongkai的回答。
Thread t3 = new Thread(new MyThread());
Thread t4 = new MyThread();
上面两种定义方式,t3.start()后,启动此线程,调用流程是MyThread类的run()方法。因为它们调用的构造器是
Thread(Runnable target),此时Thread类的target就等于new MyThread()这个对象,所以它会直接调用target.run()这个方法。
而t4.start()后,启动此线程是通过JVM调用的start0()方法,再调用的run()的一个流程。
这样理解正确吗?
问题补充:问题补充。
AngelAndAngel 写道
调用start的时候不是马上调用run方法,而是触动调用了run。
但是你要是自己调用也不是不行(不会有线程调用的效果而已,这样和普通方法就木有区别了),只是说线程得通过启动(start)来调用
但是你要是自己调用也不是不行(不会有线程调用的效果而已,这样和普通方法就木有区别了),只是说线程得通过启动(start)来调用
问题补充:问题补充
chen_yongkai 写道
public synchronized void start() { if (started) throw new IllegalThreadStateException(); started = true; group.add(this); start0(); } private native void start0();
在start0()方法中jvm调用run()方法,因为是native所以看不到源码。
问题补充:对头,我怎么木有想到呢~ 谢谢啦。
chen_yongkai 写道
static class MyThread extends Thread { @Override public void run() { System.out.println("in MyThread() run()."); } }
你已经覆盖了Thread 的run方法,就没有什么target的说法了
public void run() { if (target != null) { target.run(); } }
相关问答
更多-
关于Thread类的start方法[2022-02-15]
看一下Thread类的源码,也许你就能搞清楚为身么文档里这样解释。 这是Thread类的run()方法的代码。一目了然如果target存在的话执行target的run()方法,否则什么也不做。这样我们可以推测(因为Thread 实际运行的方法start0 是native方法 我们看不到它的实现)也就是说Thread的run()方法总是先被调用的,然后调用taget(构造函数中的Runnable对象)的run()方法。 public void run() { if (target != null) { tar ... -
关于Thread类的start方法[2022-01-09]
看一下Thread类的源码,也许你就能搞清楚为身么文档里这样解释。 这是Thread类的run()方法的代码。一目了然如果target存在的话执行target的run()方法,否则什么也不做。这样我们可以推测(因为Thread 实际运行的方法start0 是native方法 我们看不到它的实现)也就是说Thread的run()方法总是先被调用的,然后调用taget(构造函数中的Runnable对象)的run()方法。 public void run() { if (target != null) { tar ... -
Python中Thread类的start和run方法的区别[2024-02-02]
这是python实现多线程时启动多线程的两种方法,如果是start方法,你需要实现一个函数,或者一个类,里面包含了一个可执行函数,然后通过start把函数名和其参数传进去就可以了; 如果使用run方法,那么你要定义一个类,并且继承Thread类实现软方法那么你可以这样启动:子类的对象.run()即可 -
请解释Thread run()和start()方法的输出(Please explain the output from Thread run() and start() methods)[2021-09-16]
Thread.start()方法启动一个新线程,此线程的入口点是run()方法。 如果直接调用run(),它将在同一个线程中执行。 考虑到调用Thread.start()将启动一个新的执行线程, run()方法可能会在执行主方法的其余部分之后调用(就像在本例中那样)。 改变你的主要方法来调用th1.start()并重复运行,你会看到有时会输出: EXTENDS RUN>> RUNNABLE RUN >> 有时会输出: RUNNABLE RUN >> EXTENDS RUN>> 取决于java如何选择安排 ... -
在Thread类中运行方法(run method in Thread class)[2023-06-07]
请仔细查看Thread类的run方法的实现,如下所示: public void run() { if (target != null) { target.run(); } } 因此,调用Thread的run方法会调用传递的Runnable的运行,在您的情况下,您在创建Thread t时传递了A的实例。 因此,调用super.run()调用Thread类的run方法,该方法又调用A的run方法(可运行或目标)。 See carefully the implemen ... -
我认为最好的做法是拥有两个独立的线程。 您可以(也可能应该)编写一个实现Runnable的新类,并在其中放置您的逻辑。 如果您必须实现两个业务逻辑之间的共同活动,则可以将此类用作两个“Runnables”的基类。 每个Runnable应该在一个单独的线程中生成。 你可以在这篇文章中找到Thread vs. Runnable非常好的推理: “implements Runnable”vs.“extends Thread” I think that the best course of action would ...
-
什么是线程启动方法的需要?(What is the need of Thread start method? why not have only run method? [duplicate])[2022-08-16]
您需要知道该线程可以具有不同的状态。 根据http://www.tutorialspoint.com/java/java_multithreading.htm有5个线程状态 新线程已创建并可以启动 runnable - 正在执行线程 等待 - 线程正在等待其他线程完成; 其他线程必须通过调用共享锁的notify方法来通知该线程它完成了 定时等待 - 类似于等待,但线程将在一段时间后自动停止等待,而不等待来自其他线程的信号 终止 - 线程完成其任务 run方法只包含线程工作时(当它处于可运行状态时)需要执行的 ... -
是的,线程将在执行方法时阻塞,因此它无法同时从套接字读取。 没有信息会丢失,传输只需要更长的时间,如果计算时间过长,您可以获得套接字超时。 如果您的方法需要很长时间才能运行,那么您应该在另一个工作线程中执行它。 我建议使用Executor 。 Yes, the thread will block while executing the method, so it can not read from the socket at the same time. No information will be los ...
-
检查你的日志。 我的猜测是因为你试图从一个线程创建Toast而出现错误。 对于Toast命令以及影响ui的所有其他调用,应将其包装在runOnUiThread()中。 Check your log. My guess is that there is an error because you are trying to create a Toast from a thread. For the Toast command, and all other calls that affects the ui, y ...
-
停止从Controller继承: controller = Controller() thread = threading.Thread(target=controller.run_forever) Stop inheriting from Controller: controller = Controller() thread = threading.Thread(target=controller.run_forever)