进程与线程 (2010-3-36) Java: 单继承多实现 Servlet : 多实现单继承 进程与线程的联系: •线程是进程中的一部分,当一个线程消失,进程不一定会消失,但是当进程消失时,线程一定会消失。 •线程是在进程的基础上成立 •将Tomcat看做进程。垃圾回收可以看成线程 •实现多线程的两种方式: 1. 实现Runable接口 ,实现run()方法 package demo; /** * 创建一个类去实现 Runnable 接口并实现run()方法 * */ public class Runner implements Runnable{ public void run() { //让线程循环执行 while(true){ System.out.println("rrrr"); try { //让线程睡眠时间 Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } 2. 继承Threed类,重写run()方法 package demo; /** * 创建一个类去继承Thread,重写run()方法; * */ public class Thread1 extends Thread { @Override public void run() { //让线程在循环执行 while(true){ System.out.println("ttttttt"); try { //线程等待的时间 Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } } } } Main方法的实现 package demo; public class T { /** * @param args */ public static void main(String[] args) { Thread1 thread1 = new Thread1(); thread1.start(); // thread1.run();就是死循环,一直在while里面 Thread thread = new Thread(new Runner()); thread.start(); } } •线程:根据CPU分配的空间去实现,其中区别:(接口和类的区别) •Runable接口只用run()方法。 •Thread类提供多个方法 并发的概念:同一时间多个线程访问同一个资源 在同一个时间内有多个线程去访问同一个资源,那么在CPU分配的时间段中,A线程的数据可能出现获取不完整,而B线程又在执行中,获取同样的资源,将得到不完够整的数据。 例子:获取唐伯虎与如花的name与sex package demo; class Student { String name; String sex; public Student(String name,String sex) { this.name=name; this.sex=sex; } } //线程A访问同一个资源Student class ChangeStudentInfo extends Thread { // Object obj = new Object(); //传的是引用,所以stu可以被锁定 Student stu=null; //将对象当作参数 public ChangeStudentInfo(Student stu) { this.stu=stu; } //重写Thread的run()方法 public void run() { int i=0; while(true) { // //锁定对象 // synchronized (stu) { //锁定本类 synchronized (this) { if(i==0) { stu.name="唐伯虎"; stu.sex="男"; } else { stu.name="如花"; stu.sex="女"; } i=(i+1)%2; } } } } //线程B访问同一个资源Student class PrintStudent extends Thread { // Object obj = new Object(); Student stu=null; public PrintStudent(Student stu) { this.stu=stu; } public void run() { while(true) { // //锁定对象 // synchronized (stu) { //锁定本类获取资源 synchronized (this) { System.out.println(stu.name + "---->" + stu.sex); } } } } public class BoyAndGirl { public static void main(String [] args) { Student stu=new Student("唐伯虎","男"); new ChangeStudentInfo(stu).start(); new PrintStudent(stu).start(); } } 解决: Syncheronizeb()同步。当存在多个线程访问同个资源,必须等待获取资源的完整性后方可使用 •锁定对象: •CPU在一定时间段后停止,锁对象会在A线程中获取数据,B线程将等待A线程获取资源后方可执行操作资源。如果在CPU分配的时间段不足以让A线程获取完整的数据,那么B线程只能等待下一个分配时间段 •锁定方法 CPU在分配线程时。锁定方法将会不断的去串行 死锁:两个线程相互锁住资源有互索数据不肯放开 例子:发生西餐问题 解决: •锁定两个资源后,让其中某个线程的sleep()方法控制线程的睡眠时间 •用Object中的notify()方法唤醒处于睡眠状态的莫个线程。使用notifyAll()方法将唤醒所有资源 •Object中的wait()方法可以让线程在等待池中等待释放 package demo; /** * *********死锁**************** * 证明wait或notify只能是你拥有的资源 */ public class OkDeadLockTest implements Runnable { public boolean flag = true; static Object fork = new Object(); static Object sword = new Object(); public void run() { if(flag) { /**//* 锁定资源fork */ synchronized(fork) //锁住叉 { System.out.println("Resource fork is locked. Waiting for Resource sword."); try { //因为无论1睡了多久,因为2要用到1释放的fork,所以就算2醒后也是要等的。 Thread.sleep(2000); fork.wait(); System.out.println("1111111 wake up"); } catch (InterruptedException e) {} /**//* 锁定资源sword */ synchronized(sword){ System.out.println("1 Complete."); } } } else { /**//* 锁定资源sword */ synchronized(sword) //锁住刀 { System.out.println("Resource sword is locked. Waiting for Resource fork."); try { Thread.sleep(1000); } catch (InterruptedException e) {} /**//* 锁定资源fork */ synchronized(fork) { System.out.println("2 Complete."); fork.notify(); //这个证明notify之后线程1就活的,会隔一会有给他cpu时间就运行,直到运行完 // try { // Thread.sleep(2000); // } catch (InterruptedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } //这个证明线程1的synchronized(fork)还是有效的 // while(true){ // // } } } } } public static void main(String[] args) { OkDeadLockTest r1 = new OkDeadLockTest(); OkDeadLockTest r2 = new OkDeadLockTest(); r2.flag = false; Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); t2.start(); // t1.start(); } }