一、线程的基本概念
简单的说:线程就是一个程序里不同的执行路径,在同一个时间点上cpu只会有一个线程在执行,Java里的多线程是通过java.lang.Thread类来实现的,每个线程都拥有自己独立的方法栈空间。
二、java线程的创建和启动
第一种
定义线程类实现Runnable接口:
Thread myThread = new Thread(target) //target为Runnable接口类型
Runnable中只有一个方法:
public void run();用以定义线程运行体
第二种
可以定义一个Thread的子类并重写其run方法:
class MyThread extends Thread{ public void run(){} }
线程类必须通过执行Thread的start()方法启动一个新的线程,如果调用run()方法是属于方法的调用,不会启动一个新的线程,推荐使用第一种方式创建线程,使用接口较为灵活。
三、线程状态装换
调用线程start()方法时,线程进入就绪状态,Cpu分配时间片,线程进入运行状态,时间片结束,run()方法未执行完,线程进入阻塞状态。
四、线程控制基本方法
isAlive() //判断线程是否还“活着”,即线程是否还未终止
getPriority() //获得线程的优先级数值
setPriority() //设置线程的优先级指数
Thread.sleep() //静态方法,将当前线程睡眠指定毫秒数
join() //调用某线程的该方法,将当前线程与该线程合并,
//即等待该线程结束,再回复当前线程的运行。
yield() //让出CPU,当前线程进入就绪状态等待调度
interrupt() //中断线程
wait() //当前线程进入对象的wait pool
notify()/all //唤醒对象的wait pool中的一个/所有等待线程
五、sleep方法
Thread的静态方法
public static void sleep(long millis)throws InterruptedException
必须对异常进行捕捉
Thread.currentThread(); //拿到当前线程
六、interrupt方法一种让线程退出的方式。
import java.util.*; public class TestInterrupt{ public static void main(String[] args){ MyThread t = new MyThread(); t.start(); try{Thread.sleep(10000);} catch(InterruptedException i){} t.interrupt(); } } class MyThread extends Thread{ public void run(){ while(true){ try{ System.out.println("------"+new Date()+"-----"); Thread.sleep(1000); }catch(InterruptedException i){ return; } } } }
七、join和yield方法
t.join(); //t的run()方法完才会继续执行当前线程方法体
//也就是两个线程变成了一个线程
t.yield(); //暂停当前正在执行的线程对象,并执行其他线程。方法为静态
//哪个线程体执行此方法,哪个线程让步
public class TestYield { public static void main(String[] args) { MyThread3 t1 = new MyThread3("t1"); MyThread3 t2 = new MyThread3("t2"); t1.start(); t2.start(); } } class MyThread3 extends Thread { MyThread3(String s){super(s);} public void run(){ for(int i =1;i< =100;i++){ System.out.println(getName()+": "+i); if(i%10==0){ yield(); } } } }
八、线程优先级别
线程的优先级用数字表示,范围从1到10,一个线程的缺省优先级为5.
Thread.MAX_PRIORITY=1
Thread.MIN_PRIORITY=10
Thread.NORM_PRIORITY=5
例:t.setPriority(Thread.NORM_PRIORITY+3);
九、线程同步
1.同步代码块
synchronized(this){ //在执行代码块过程中,不会被其他线程打断
…
}
public sunchronized void method //执行此方法时,当前对象被锁定
在Java语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性,每个对象 都对应一个可称为”互斥锁”的标记,这个标记保证在任一时刻,只能有一个线程访 问该对象。
2.线程死锁
public class TestDeadLock implements Runnable { public int flag = 1; static Object o1 = new Object(), o2 = new Object(); public void run() { System.out.println("flag=" + flag); if(flag == 1) { synchronized(o1) { try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } synchronized(o2) { System.out.println("1"); } } } if(flag == 0) { synchronized(o2) { try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } synchronized(o1) { System.out.println("0"); } } } } public static void main(String[] args) { TestDeadLock td1 = new TestDeadLock(); TestDeadLock td2 = new TestDeadLock(); td1.flag = 1; td2.flag = 0; Thread t1 = new Thread(td1); Thread t2 = new Thread(td2); t1.start(); t2.start(); } }
十、生产者消费者问题
public class ProducerConsumer { public static void main(String[] args) { SyncStack ss = new SyncStack(); Producer p = new Producer(ss); Consumer c = new Consumer(ss); new Thread(p).start(); new Thread(p).start(); new Thread(p).start(); new Thread(c).start(); } } class WoTou { int id; WoTou(int id) { this.id = id; } public String toString() { return "WoTou : " + id; } } class SyncStack { //栈实现 int index = 0; WoTou[] arrWT = new WoTou[6]; //相当于装物品的篮子 public synchronized void push(WoTou wt) { //生产物品,线程安全 while(index == arrWT.length) { //当篮子满了线程等待 try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll(); //开始生产时,叫醒等待的其他线程开始消费 arrWT[index] = wt; index ++; } public synchronized WoTou pop() { //消费物品,线程安全 while(index == 0) { //如果篮子空了 try { this.wait(); //线程等待,等待生产者开始 //生产,叫醒此线程 } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll(); //消费时喊醒生产者生产 index--; return arrWT[index]; } } class Producer implements Runnable { //生产者类 SyncStack ss = null; Producer(SyncStack ss) { this.ss = ss; } public void run() { for(int i=0; i<20; i++) { //生产20个 WoTou wt = new WoTou(i); ss.push(wt); System.out.println("生产了:" + wt); try { Thread.sleep((int)(Math.random() * 200)); } catch (InterruptedException e) { e.printStackTrace(); } } } } class Consumer implements Runnable { SyncStack ss = null; Consumer(SyncStack ss) { this.ss = ss; } public void run() { for(int i=0; i<20; i++) { //消费20个 WoTou wt = ss.pop(); System.out.println("消费了: " + wt); try { Thread.sleep((int)(Math.random() * 1000)); } catch (InterruptedException e) { e.printStackTrace(); } } } }上一篇: 初识Java多线程设计要点 下一篇: 警惕!Java多线程编程的常见陷阱