1 线程的定义
进程:一个程序的执行过程
线程:一个程序中一个任务的执行(一个程序可能由一个或多个任务构成,这些任务可能并行或串行执行)
多个线程分享资源:CPU(以并发或者时间片的形式)、共享内存(多个线程共享同一个对象)
2 线程的创建
java中线程在java.lang包Thread类中
线程的创建有两种方法:
2.1 通过继承Thread类实现
public class MyThread extends Thread{ public void run(){ //执行任务 } } MyThread myThread = new MyThread(); myThreas.start()
2.2 通过向Thread类的Thread()构造方法传递一个runnable对象
class MyTask implements Runnable{ public void run(){ //执行任务 } } MyTask myTask = new MyTask(); Thread myThread = new MyThread(myTask); myThread.start();
3 线程的控制
3.1 线程的状态与生命周期
3.2 线程控制
start()----开启
标记变量 -----结束死循环线程
暂时阻止线程的执行---Thread.sleep()
3.3 设置线程优先级
setPriority()-----MIN_PRIORITY,MAX_PRIORITY,NORM_PRIORITY
3.4 线程种类
普通线程(非Daemon线程)----决定线程存在与否
后台线程(Daemon线程)-------后台线程(如垃圾回收)跟随进程结束而结束
4 线程同步
4.1 线程的不确定性
class TestThreadCount { public static int cnt=0; public static void main(String[] args) { final int NUM=5000; Thread [] threads = new Thread[NUM]; for(int i=0; i<NUM; i++){ threads[i] = new Thread(){ public void run(){ cnt++; try{ Thread.sleep(1); } catch(InterruptedException ex){} } }; } for(int i=0; i<NUM; i++) threads[i].start(); try{ Thread.sleep(3000); } catch(InterruptedException ex){} System.out.printf("%d %b ", cnt, cnt==NUM); } }
4.2 多线程同步
同时运行的线程需要共享数据
4.2.1 互斥锁
- 互斥锁用来保证共享数据操作的完整性
- 每个对象对应一个monitor,它上面有一个陈伟互斥锁(lock mutex)的标记,这个标记用来保证,在任一时刻,只能有一个线程访问该对象
- 关键字synchronized用来与对象的互斥锁配合使用(使得对应的语句原子化)
4.2.2 synchronized用法
- 对于代码片段:synchronized(对象){.......}
- public synchronized void push(){。。。。。。}
- synchronized用于对象和类表示该对象或者该类的实例同一时刻只能有一个线程操作该对象,获得对象锁
- 用于代码块和方法表示该只能有一个线程进入该方法或者代码块 获得成员锁
4.2.3 线程同步控制
- 使用wait()方法可以释放互斥锁
- notify()或notifyAll()可以让等待的一个或者所有线程进入就绪状态java中可以见notify或wait放入synchronized中,在synchronized代码被执行期间,线程调用对象的wait()方法,会释放对象锁标志,然 后进入等待状态,然后由其它线程调用notify()或者notifyAll()方法通知正在等待的线程。
public class ProducerConsumerStack { public static void main(String arg[]){ CubbyHole cubby = new CubbyHole(); Producer pro = new Producer(cubby,3); pro.start(); Consumer con = new Consumer(cubby); Thread thread = new Thread(con); thread.start(); try{ Thread.sleep(1000); }catch(InterruptedException e){ } } } class CubbyHole{ public int index = 0; public int[] data = new int[4]; public synchronized void put(int value){ while(index >= data.length){ try{ this.wait(); }catch(InterruptedException e){}; } System.out.println("Producer " + " put: " + value); data[index] = value; if(index < data.length) index++; this.notify(); } public synchronized int get(){ while(index <= 0){ try{ this.wait(); }catch(InterruptedException e){}; } index--; int value = data[index]; System.out.println("Consumer " + " got: " + data[index]); this.notify(); return value; } } class Producer extends Thread{ private CubbyHole cubbyHole = null; private int value=0; Producer(CubbyHole cubbyHole, int value){ this.cubbyHole = cubbyHole; this.value = value; } public void run(){ for(int i=0; i<=10; i++){ cubbyHole.put(i); } } } class Consumer implements Runnable{ private CubbyHole cubbyHole = null; Consumer(CubbyHole cubbyHole){ this.cubbyHole = cubbyHole; } public void run(){ for(int i=0; i<=8; i++){ cubbyHole.get(); } } }
4.2.4 线程的锁死
synchronized(this)独占该资源,我在使用,别人不能使用。
public class DeadLock { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub final Worker w1 = new Worker(1); final Worker w2 = new Worker(2); Thread td1 = new Thread(){ public void run(){ w1.doTaskWithCooperator(w2); } }; Thread td2 = new Thread(){ public void run(){ w2.doTaskWithCooperator(w1); } }; td1.start(); td2.start(); } } class Worker{ int id; public Worker(int id){this.id = id;} synchronized void doTaskWithCooperator(Worker other){ try{ Thread.sleep(1000);}catch(InterruptedException e){} synchronized(other){ System.out.println("doing" + id); } } }
4.3 并发API
从java1.5开始,java.util.concurrent包及其子包,提供了一系列的工具,更好、更方便地使用线程,如单变量、集合、Timer、线程池
4.3.1 原子变量
- 位于java.util.concurrent.atomic包
- AtomicInteger类,getAndIncrement()方法
4.3.2 集合与线程
- 位于java.util.concurrent包
- CopyOnWriteArrayList、 CopyOnWriteArraySet ,适合于很少写入而读取频繁的对象
- ConcurrentHashMap:putIfAbsent(), remove(), replace()
- ArrayBlockingQueue:生产者与消费者,使用put()及take()
4.3.3 线程池
- 线程池相关的类:ExecutorService 接口、ThreadPoolExecutor 类 、Executors 工具类
- 常见的用法 :ExecutorService pool = Executors.newCachedThreadPool(); 使用其execute( Runnable r)方法
import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ThreadPoolDemo { public static void main(String[] args) { // TODO Auto-generated method stub MyThreadTask task1 = new MyThreadTask(4); MyThreadTask task2 = new MyThreadTask(5); ExecutorService pool = Executors.newCachedThreadPool(); pool.execute(task1); pool.execute(task2); } } class MyThreadTask implements Runnable{ int n = 10; public MyThreadTask(int n){ this.n = n; } public void run(){ for(int i=0; i<=n; i++) System.out.println(i); } }
4.3.4 Timer的使用
- 使用 java.util.Timer 类----重复某件事
import java.util.Timer; import java.util.TimerTask; public class TimerTest { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub Timer timer = new Timer(); MyTimer task = new MyTimer(10); timer.schedule(task, 1000,1000); } } class MyTimer extends TimerTask{ int times = 0; public MyTimer(int times){ this.times = times; } public void run(){ System.out.println( new java.util.Date().toString()); } }
- 使用 javax.swing.Timer 类----重复执行ActionListener
import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JFrame; import javax.swing.Timer; public class TimerSwing extends JFrame { /** * @param args */ Timer timer; public void init(){ setLayout(null); setSize(400,400); setDefaultCloseOperation(EXIT_ON_CLOSE); setVisible(true); ActionListener taskperformer = new ActionListener(){ public void actionPerformed(ActionEvent e){ setTitle(new java.util.Date().toString()); } }; timer = new Timer(1000,taskperformer); timer.start(); } public static void main(String[] args) { // TODO Auto-generated method stub new TimerSwing().init(); } }