一.理解程序、进程、线程、
1. 程序是计算机指令的集合,它以文件的形式存储在磁盘上。
1.继承自Thread
2.实现runnable接口
(1) Java运行时系统实现了一个用于调度线程执行的线程调度器,用于确定某一时刻由哪一个线程在CPU上运行。
(2) 在java技术中,线程通常是抢占式的而不需要时间片分配进程(分配给每个线程相等的CPU时间的进程)。抢占式调度模型就是许多线程处于可以运行状态(等待状态),但实际上只有一个线程在运行。该线程一直运行到它终止进入可运行状态(等待状态),或者另一个具有更高优先级的线程变成可运行状态。在后一种情况下,低优先级的线程被高优先级的线程抢占,高优先级的线程获得运行的机会。
(3) Java线程调度器支持不同优先级线程的抢先方式,但其本身不支持相同优先级线程的时间片轮换。
(4 ) Java运行时系统所在的操作系统(例如:Windows2000)支持时间片的轮换,则线程调度器就支持相同优先级线程的时间片轮换。
第一个方法就是继承线程类这个类本身也实现了Runnable接口。Thread类里有一些方法,如 Static Thread currentThread(),getName(),setDaemon()(设置为后台线程,在main()方法里运行的线程并不是一个后台线程,另外这个方法对高优先级线程是不起作用的),yield(线程暂时停下),static sleep() 。设置优先级可以在线程启动之后也可以在线程启动之前,注意不要过分以来高优先级线程。
在Thread 中有一个构造方法需要一个实现了Runnable接口的类来创建,这样有利于共享同一个对象的变量,相比直接继承Thread,一般我们也采用这种方法,另外我们也可以采用内部类灵活的实现变量的共享。
class MultiThread
{
public static void main(String[] args)
{
MyThread mt=new MyThread();
/*new Thread(mt).start();
new Thread(mt).start();
new Thread(mt).start();
new Thread(mt).start();*/
mt.getThread().start();
mt.getThread().start();
mt.getThread().start();
mt.getThread().start();
//mt.setDaemon(true);
//mt.setPriority(Thread.MAX_PRIORITY);
//mt.start();
int index=0;
while(true)
{
/*if(index++==1000)
break;*/
System.out.println("main:"+Thread.currentThread().getName());
}
}
}
3.线程的同步和死锁
n 同步的两种方式:同步块和同步方法
n 每一个对象都有一个监视器,或者叫做锁。(可以是任意对象,也可以是this对象)
n 同步方法利用的是this所代表的对象的锁。
n 每个class也有一个锁,是这个class所对应的Class对象的锁。(对于静态方法用的就是class对象的监视器)
当对共享变量进行连续操作时,同步块和同步方法必须使用的是同一个对象的同步块。
线程1锁住了对象A的监视器,等待对象B的监视器,线程2锁住了对象B的监视器,等待对象A的监视器,就造成了死锁。suspend(),resume()方法已经被废弃,因为容易造成线程死锁。
4.wait、notify、notifyAll
n 每一个对象除了有一个锁之外,还有一个等待队列(wait set),当一个对象刚创建的时候,它的对待队列是空的。
n 我们应该在当前线程锁住对象的锁后,去调用该对象的wait方法。
n 当调用对象的notify方法时,将从该对象的等待队列中删除一个任意选择的线程,这个线程将再次成为可运行的线程。
n 当调用对象的notifyAll方法时,将从该对象的等待队列中删除所有等待的线程,这些线程将成为可运行的线程。
n wait和notify主要用于producer-consumer这种关系中。
Wait()、notify()必须用在同步方法或同步块当中,注意不许使用的是同一个对象的等待队列。
class Test { public static void main(String[] args) { Queue q=new Queue(); Producer p=new Producer(q); Consumer c=new Consumer(q); p.start(); c.start(); } } class Producer extends Thread { Queue q; Producer(Queue q) { this.q=q; } public void run() { for(int i=0;i<10;i++) { q.put(i); System.out.println("Producer put "+i); } } } class Consumer extends Thread { Queue q; Consumer(Queue q) { this.q=q; } public void run() { while(true) { System.out.println("Consumer get "+q.get()); } } } class Queue { int value; boolean bFull=false; public synchronized void put(int i) { if(!bFull) { value=i; bFull=true; notify(); } try { wait(); } catch(Exception e) { e.printStackTrace(); } } public synchronized int get() { if(!bFull) { try { wait(); } catch(Exception e) { e.printStackTrace(); } } bFull=false; notify(); return value; } }