一个Java线程就像一个可以执行你的Java代码的虚拟CPU。
当Java虚拟机创建的主线程开始执行main方法时,你的Java应用程序启动,在你的Java应用程序里面你可以创建和开始你自定义的线程。
Java 线程都是对象,就像其他的Java对象一样,线程对象都是 java.lang.Tread 的实例或者其子类的实例。
你可以像这样创建一个线程对象:
Thread myThread = new Thread();你可以像这样开始一个线程:
myThread.start();创建线程的几种方式:
继承 java.lang.Thread 类并重写 run() 方法。实现 java.lang.Runnable 接口并重写 run() 方法。实现 java.util.concurrent.Callable 接口并重写 call() 方法。继承 java.lang.Thread 类并重写 run() 方法
//Thread子类 public class MyThread extends Thread { public void run(){ System.out.println("MyThread running"); } } //main方法 public static void main(String[] args){ MyThread myThread = new MyThread(); myThread.start(); }start() 方法不会等线程执行完 run()方法,run() 方法将会由不同的线程执行。
第二种创建线程的方式是实现 java.lang.Runnable 接口并重写该接口的 run() 方法。一个 Java 对象实现 Runnable 接口 可以被Java Thread 类执行。
Runnable 接口由 JDK 提供,仅有一个 run 方法,是一个函数式接口。源码如下:
@FunctionalInterface public interface Callable<V> { /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ V call() throws Exception; }实现 Runnable 的方式有3种:
创建一个 Java 类实现 Runnable 接口创建一个 Java 匿名类实现 Runnable 接口使用 Java 8 Lambda 表达式实现 Runnable 接口例如:
public class MyRunnable implements Runnable { public void run(){ System.out.println("MyRunnable running"); } }例如:
Runnable myRunnable = new Runnable(){ public void run(){ System.out.println("Runnable running"); } }例如:
Runnable runnable = () -> { System.out.println("Lambda Runnable running"); };java.lang.Thread的包含传入一个Runnable接口的构造函数。
public static void main(String[] args) { //or an anonymous class, or lambda... Runnable runnable = new MyRunnable(); //executed by a thread Thread thread = new Thread(runnable); thread.start(); }关于继承Thread和实现Runnable接口,没有明确的规定用哪种方式创建线程更好,两种方式都可以让线程运行。我更倾向于使用实现Runnable接口的方式,后面我还们会了解到另外一种创建线程的方式,通过线程池创建线程的方式更加合理。
通过调用start(),程序会告诉 CPU 线程已准备就绪,等待CPU执行 run() 方法。若直接调用 run() 方法则不会开启一个新的线程去执行 run() 方法,而是在原来的线程中去执行 run() 方法,所以当我们需要一个新的线程去执行 run() 方法中的代码时,应该调用 start() 方法启动一个线程,而不是直接调用 run() 方法。
创建线程的时候可以指定线程名称,详见 java.lang.Thread API
public static void main(String[] args) { Runnable myRunnable = () -> System.out.println("Thread name is " + Thread.currantThread().getName()); new Thread(myRunnable, "Thread One").start(); } console out: Thread name is Thread One通过 Thread.currentThread() 获取当前正在执行的线程对象。
Thread currentThread = Thread.currentThread();可以通过 Thread.sheep() 让线程睡眠指定毫秒数。这里不建议使用 thread.suspend() 方法,该方法和 Thread 类的 resume()、stop()、destroy() 都是 JDK 标注废弃方法。
try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); }注意: Thread.sheep() 方法不会释放CPU资源,如果设置锁的话也不会释放锁资源,只是让线程睡眠指定毫秒数。与 Object 类的 wait() 方法不同, wait() 方法主要用于线程通信,且 wait() 方法会释放锁资源。
不建议使用 Thread 类提供的 stop() 方法去停止一个线程,stop() 方法会暴力停止一个线程,对程序不友好,可以通过更友好的方式停止一个线程。
请看示例:
public class MyRunnable implements Runnable { private boolean doStop = false; public synchronized void doStop() { this.doStop = true; } private synchronized boolean keepRunning() { return this.doStop == false; } @Override public void run() { while(keepRunning()) { // keep doing what this thread should do. System.out.println("Running"); try { Thread.sleep(3L * 1000L); } catch (InterruptedException e) { e.printStackTrace(); } } } }请注意 doStop() 方法和 keepRunning() 方法使用了 synchronized 关键字,后面会详细讲解 synchronized 关键字的作用,这里不做过多描述。
public class MyRunnableMain { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start(); try { Thread.sleep(10L * 1000L); } catch (InterruptedException e) { e.printStackTrace(); } myRunnable.doStop(); } }上面示例通过设置一个标识,主线程里面启动子线程,然后主线程睡眠10秒钟后调用 doStop() 方法,实现在主线程中停止子线程的运行。