一、基本概念:程序 - 进程 - 线程
l 程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。
l 进程(process)是程序的一次执行过程,或是正在运行的一个程序。动态过程:有它自身的产生、存在和消亡的过程。
- 如:运行中的QQ,运行中的MP3播放器
- 程序是静态的,进程是动态的
l 线程(thread),进程可进一步细化为线程,是一个程序内部的一条执行路径。
- 若一个程序可同一时间执行多个线程,就是支持多线程的
二、线程的创建:
1.继承java.lang.Thread, 类中重写Thread类中的run方法.
2.实现Runnable接口, 子类中重写Runnable接口中的run方法(推荐).
Note : public class Thread extends Object implements Runnable
l void start(): 启动线程,并执行对象的run()方法
l run(): 线程在被调度时执行的操作
l String getName(): 返回线程的名称
l void setName(String name):设置该线程名称
l static currentThread(): 返回当前线程
l static void yield():线程让步
- 暂停当前正在执行的线程,把执行机会让给优先级相同或更高的线程,但有可能再次获得CPU资源
- 若队列中没有同优先级的线程,忽略此方法
l join() :当某个程序执行流中调用其他线程的 join() 方法时,调用线程将被阻塞,直到 join() 方法加入的 join 线程执行完为止
- 在线程A中调用B线程的 join() 方法, A线程挂起直到B线程执行完毕或消亡
l static void sleep(long millis):(指定时间:毫秒)
- 令当前活动线程在指定时间段内放弃对CPU控制,使其他线程有机会被执行,时间到后重排队(自动从阻塞到就绪)。
- 抛出InterruptedException异常
l stop(): 强制线程生命期结束
l boolean isAlive():返回boolean,判断线程是否还活着
三、线程的生命周期
四、线程的同步
背景:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误。
解决:对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。-->同步机制
1.同步代码块
synchronized (对象){
// 需要被同步的代码;
}
2.同步方法
synchronized还可以放在方法声明中,表示整个方法为同步方法。
例如:
public synchronized void show (String name){
….
}
互斥锁:
同步方法锁对象:this
静态锁对象:当前类的class对象
同步代码块锁对象:任意对象
当前线程正常或异常结束时会释放锁,以及调用线程的wait() 方法。
程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行时不会释放锁。
class Singleton { private static Singleton instance = null; private Singleton(){} public static Singleton getInstance(){ if(instance==null){ synchronized(Singleton.class){ if(instance == null){ instance=new Singleton(); } } } return instance; } } public class TestSingleton{ public static void main(String[] args){ Singleton s1=Singleton.getInstance(); Singleton s2=Singleton.getInstance(); System.out.println(s1==s2); } }
五、线程的通信
l wait() 与 notify() 和 notifyAll()
- wait():令当前线程挂起并放弃CPU、同步资源,使别的线程可访问并修改共享资源(释放锁),直到另一线程对该对象发出 notify (或notifyAll) 为止。
- notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待
- notifyAll ():唤醒正在排队等待资源的所有线程结束等待.
l Java.lang.Object提供的这三个方法只有在synchronized方法或synchronized代码块中才能使用,否则会报java.lang.IllegalMonitorStateException异常
package com.test; public class CrossPrint { public static void main(String[] args) { Print p = new CrossPrint().new Print(); Thread t1 = new Thread(p); Thread t2 = new Thread(p); t1.start(); t2.start(); } class Print implements Runnable { int num = 1; @Override public void run() { while (true) { synchronized (this) { notify(); if (num <= 100) { System.out.println(Thread.currentThread().getName() + ":" + num); num++; } else { break; } try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } } }