java中线程Thread的使用
1、创建的线程方式
线程的创建有两种方式,这里先直接上例子,然后再介绍两者的区别
1.1、继承Thread类
1.1.1、FirstThread
package multithread.thread;
public class FirstThread extends Thread{
@Override
public void run() {
super.run();
System.out.println("通过继承Thread的方式创建的线程FirstThread运行结束");
}
}
1.1.2、ThreadTest
package multithread.main;
import multithread.thread.FirstThread;
public class ThreadTest {
public static void main(String[] args) {
FirstThread firstThread = new FirstThread();
firstThread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main线程在执行完start方法后已沉睡一秒结束,main线程执行完毕,");
}
}
1.1.3、执行结果
1.2、实现Runnable接口
1.2.1、 FirstRunnable
package multithread.thread;
public class FirstRunnable implements Runnable {
@Override
public void run() {
System.out.println("通过实现runnable的方式创建线程FisrtRunnable运行结束");
}
}
1.2.2、ThreadTest
package multithread.main;
import multithread.thread.FirstRunnable;
public class ThreadTest {
public static void main(String[] args) {
Thread thread = new Thread(new FirstRunnable());
thread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("main线程在执行完start方法后已沉睡一秒结束,main线程执行完毕,");
}
}
1.2.3、执行结果
1.3、Thread与Runnable两种方式的区别
1.3.1、Runnable
package java.lang;
@FunctionalInterface
public 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();
}
可以看到Runnable接口定义了一个run方法,而线程规划器在调用线程时,就是执行线程实现的run方法。
1.3.2、Thread类结构
可以看到Thread其实也是实现了Runnable接口,线程规划器调用线程时也是调用Thread类实现的runnable接口的run方法。这个run方法可以被继承Thread类的子类重写,因此线程规划器最终就是调用这个子类的run方法。
1.3.3、总结
由于java是单继承的特性,如果使用了继承Thread的方式创建线程,那就没法再继承其他类了。因此使用Runnable的方式比较灵活。
2、使用线程时必须了解的注意点
2.1、调用run方法
如果直接调用Thread类的run方法即thread.run(),那么相当于普通对象调用自身方法一样,是同步的,并不是一个新的线程。
2.2、调用start方法
调用了start方法thread.start(),即通知线程规划器,当前线程已经初始化好了,准备就绪。线程规划器则会去以一个新的线程去执行run方法。
调用了start方法知识通知了线程规划器,并不代表先通知,就一定会被先执行的。在前面的代码演示中,我特意在调用了thread.start()方法后,让main线程沉睡了一秒。才能保证达到最终的打印结果。如果我把sleep的代码去掉,则有可能出现以下打印结果。
public static void main(String[] args) {
FirstThread firstThread = new FirstThread();
firstThread.start();
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println("main线程在执行完start方法后已沉睡一秒结束,main线程执行完毕,");
}
可能出现以下结果:
因此。假如main线程先后执行aThread.start()和bThread.start(),并不代表a线程的run方法一定先被执行。a和b两个线程都是线程规划器安排规划的,都有可能先被执行。