Thread 中的run() 与start() 方法
来源:互联网 发布:生产流程优化 编辑:程序博客网 时间:2024/05/30 04:29
将类声明为 Thread 的子类是创建线程的方式之一,如果我们想要在线程内定义任务那么就要重写Thread 中的run() 方法。start() 方法使我们定义的线程执行,我们已经将线程的任务定义在了run() 方法中为什么run() 方法不是执行线程的方法而是start() 方法呢?当时学线程的时候并没有多考虑这个问题,由于以前有一些误解,现在就写出来供自己与大家参考。
我定义了一个Thread 的子类ThreadTest ,在该子类中重写了run() 方法,在run() 方法中用于输出当前正在执行的线程引用,为了达到效果我让线程等待了100ms。在创建两个线程对象thread1 与thread2 后直接调用了它们的run() 方法,我们希望得到的结果是thread1 与thread2 共同抢占CPU 以达到交错输出,但是从输出的结果看出在执行的始终是主线程(main)。
public class ThreadTest extends Thread{ @Override public void run() { for(int i = 0; i < 5; i++){ try { Thread.sleep(100); //Thread.currentThread() 返回对当前正在执行的线程对象的引用 System.out.println(Thread.currentThread()); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { TestThread thread1 = new TestThread(); TestThread thread2 = new TestThread(); thread1.run(); thread2.run(); }}
输出:
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
下面我们用和上面同样的代码,不再调用ThreadTest 的run() 方法,这次调用start() 方法,看看输出结果会是什么?从下面的结果可以看出这次输出的不再是主线程,而是线程0与线程1 (但是执行的线程也包括主线程)。
public class ThreadTest extends Thread{ @Override public void run() { for(int i = 0; i < 3; i++){ try { Thread.sleep(100); //Thread.currentThread() 返回对当前正在执行的线程对象的引用 System.out.println(Thread.currentThread()); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { TestThread thread1 = new TestThread(); TestThread thread2 = new TestThread(); thread1.start(); thread2.start(); }}
输出
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
通过执行run() 方法与start() 方法可以知道Thread 并不是通过run() 方法执行线程的而是通过start() 方法执行线程,我们只是把线程的任务定义在了run() 方法中,但是它并不是执行任务的方法。我们知道创建执行线程任务还有一种方式,就是实现Runnable 接口。下面我们就来看一下Runnable 中的run() 方法,为了更好的对比我在run() 方法中定义了和上面一样的任务。通过上面的了解我们知道执行run() 方法并不能让线程执行,所以输出的仍然是主线程的引用。
public class RunnableTest implements Runnable { @Override public void run() { for(int i = 0; i < 3; i++){ try { Thread.sleep(100); System.out.println(Thread.currentThread()); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { RunnableTest runnableTest1 = new RunnableTest(); RunnableTest runnableTest2 = new RunnableTest(); runnableTest1.run(); runnableTest2.run(); }}
输出
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
Thread[main,5,main]
通过看Runnable 接口的源码你就会知道这个接口只定义了一个run() 方法,这也说明着Runnable 并不能创建线程实例,那么怎么执行在其中定义的任务呢?想要创建线程实例还不简单吗,直接new 一个Thread 对象不就好了吗。Thread类 提供了一个 Thread(Runnable target) 构造器,它允许我们传入一个Runnable 子类的实例,下面我们就来这么做。
@FunctionalInterfacepublic interface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run();}
重新定义了两个Thread 类实例并将RunnableTest 对象传入Thread 类中的构造器,然后由线程实例thread1 与thread2 执行线程任务,我们看到正如我们所希望的那样打印着执行线程的引用。
public class RunnableTest implements Runnable { @Override public void run() { for(int i = 0; i < 3; i++){ try { Thread.sleep(100); System.out.println(Thread.currentThread()); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { RunnableTest runnableTest1 = new RunnableTest(); RunnableTest runnableTest2 = new RunnableTest(); Thread thread1 = new Thread(runnableTest1); Thread thread2 = new Thread(runnableTest2); thread1.start(); thread2.start(); }}
输出
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
Thread[Thread-1,5,main]
Thread[Thread-0,5,main]
总结:
Thread 中的run() 方法只是定义了线程的任务但是它不负责执行该任务,如果你调用该方法那么执行的只是主线程,就像某一个对象实例调用它自己的方法一样。
Thread 中的start() 方法才是执行线程的方法,在执行该方法时,Java 虚拟机会调用该线程的run() 方法,从而达到并发执行的目的。在这里你需要注意的是多次启动一个线程是不安全的,特别是线程执行结束后,不要再重新启动,这点要特别注意。
在这里也通过实现Runnable 接口来定义线程任务,需要注意的是Runnable 接口的实现并不能创建线程实例,当你想要执行其中定义的任务时,你需要将该子类的实例作为参数传入Thread 中的构造器,通过Thread 类的实例来执行线程任务。
- Thread 中的run() 与start() 方法
- java中Thread类中的start()方法与run()方法
- java中Thread类中的start()方法与run()方法
- java中Thread类中的start()方法与run()方法
- Thread中的run和start方法
- Thread中的run和start方法
- Thread.run()方法与Thread.start()方法的区别
- Thread的run()方法与start()方法
- Thread 类中start方法与run方法的区别
- Thread的start与run
- Java多线程之Thread的run()与start()方法解析
- Thread的run方法和start方法
- Thread的run方法和start方法
- Thread的run方法和start方法
- Thread中的run()和start()的区别
- Thread类的start()和run()方法
- Thread的run和start方法区别
- Thread run()和start()方法的区别
- Linux基本命令二
- Android函数响应式编程——必学的RxJava转换操作符toList、toSortedList、toMap
- 几个软件安装与环境配置的网址收藏
- Selenium+PhantomJS()+PIL漫画快照
- 《OpenCV3编程入门》学习笔记一:邂逅OpenCV
- Thread 中的run() 与start() 方法
- 教大家一个关于使用微信投票刷票器免费版及微信投票刷票软件手机版的操作方式
- 使用2to3.py转换python2代码到python3
- 15.Linux多线程编程
- java关于并发的总结之二
- 通过METAMASK调试和发布智能合约指南》
- python几种编译器使用
- PID控制的MATLAB仿真(1)
- 0.96寸OLED屏使用详解