每个应用至少有一个线程 —— 主线程,可以创建其他的线程 Java中的线程类可以分为两种:
Thread. 从Thread类派生子类 (使用较少)Thread类本身实现了Runnable接口,尽管其.run()方法不执行任何操作。 因此创建一个Thread类将其作为Thread的子类,提供其自己的run()实现。
public class HelloThread extends Thread { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { HelloThread p = new HelloThread(); p.start(); } //----------启动该线程的两个方式 public static void main(String args[]) { (new HelloThread()).start(); } } 实现Runnable接口构造Thread对象 (较为常用) Runnable接口定义单个方法.run(),该方法需要包含想在线程中执行的代码。 在运行时需要将实现Runnable接口的对象传递给Thread 的构造函数 public class HelloRunnable implements Runnable { public void run() { System.out.println("Hello from a thread!"); } public static void main(String args[]) { (new Thread(new HelloRunnable())).start(); } }一个常见的用法是使用匿名内部Runnable类(需要实现run()方法)来启动线程,因此可以不必须创建新的线程类
new Thread(new Runnable() { public void run() { System.out.println("Hello"); } } ).start();首先我们对run()方法和start()方法进行实验
package main; public class Main { public static void main(String[] args) { Thread nona = new Thread(new Runnable() { public void run(){ int i=0; while(i<10) { try { Thread.sleep(100); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } System.out.println("A"+i++); } } ; } ); nona.start(); Thread nova = new Thread(new Runnable() { public void run() { int i=0; while(i<10) { try { Thread.sleep(100); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } System.out.println("B"+i++); } } ; } ); nova.start(); } }执行这段代码 如果对线程使用 .start()方法 运行结果,发现两个线程并发进行 结果: 如果我们使用.run()方法,两个线程就不是同步执行了,而是有一定的先后顺序 结果: 发现如果使用run()方法,并不会真的启动一个新的线程,而是由主线程main去调用run()方法,与我们使用线程的初衷相左。
虽然有多线程, 但只有一个核,每个时刻只能执行一个线程 ,因此通过时间分片的方式,在多个进程/线程之间共享处理器 但是,线程之间共享内存和时间切片可能会引发的错误
当发生如下情况时,线程将会进入阻塞状态:
线程调用sleep()方法主动放弃所占用的处理器资源线程调用了一个阻塞式IO方法,在该方法返回之前,该线程被阻塞线程试图获得一个同步监视器(锁),但该同步监视器正被其他线程所持有。线程在等待某个通知(notify(),notifyAll())程序调用了线程的suspend()方法将该线程挂起。但这个方法容易导致死锁,所以应该尽量避免使用该方法Thread.sleep() 线程的休眠,使线程转到阻塞状态 将某个线程休眠,意味着其他线程得到更多的执行机会 但是,进入休眠的线程不会失去对现有monitor或锁的所有权 (不会释放锁) Thread.interrupt()
t.interrupt() # 在其他线程里向t发出中断信号向线程发出中断信号 一般来说,线 程在收到中断信号时应该中断,直接终止 但是,线程收到其他线程发来的中断信号, 并不意味着一定要“停止 当某个线程被中断后,一般来说应停止其run()中代码的执行,取决于程序员在run()中处理 正常运行期间, 并不强制要求需要对中断作出响应,可以即使接收到中断信号,也不理会, 但是在线程如果在执行Thread.sleep()、 Thread.join()和Object.wait()等方法时,会立即相应中断请求
Thread.yield()
是一种线程的让步,使用该方法,线程告知调度器:我可以放弃CPU的占用权,从而可能引起调 度器唤醒其他线程,使当前线程由执行状态,变成为就绪状态,让出cpu时间,在下一个线程执行时候,此线程有可能被执行,也有可能没有被执行( 尽量避 免在代码中使用 ) Thread.join() 在线程内调用让当前线程保持执行,直到其执行结束,可以显式指定线程执行次序 ,也可以在当前线程中调用另一个线程的join()方法,则当前线程转入阻塞状态,直到另一个进程运行结束,当前线程再由阻塞转为就绪状态。 Object.wait() : 该操作使object所处的当前线程进入阻塞/等待状态,直到其他线程调用此对象的 notify() 方法或notifyAll()唤醒方法 Object.notify() : 随机(取决于操作系统对多线程管理)选择一个在该对象上调用wait方法的线程,解除其阻塞状态 ,唤醒一个正处于等待状态的线程,让他继续往下执行。 Object.notifyAll(): 唤醒所有在对象上调用wait方法的线程,解除其阻塞状态