马士兵-J2SE第九章-线程-个人学习笔记(共13页).doc
-
资源ID:16641637
资源大小:1.27MB
全文页数:13页
- 资源格式: DOC
下载积分:20金币
快捷下载
会员登录下载
微信登录下载
三方登录下载:
微信扫一扫登录
友情提示
2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
|
马士兵-J2SE第九章-线程-个人学习笔记(共13页).doc
精选优质文档-倾情为你奉上第九章 Java多线程机制线程基本概念 Runnable线程类接口线程创建和启动线程的调度好优先级线程的状态控制 sleep join yield 线程同步synchronized wait notify/notifyAll一、 线程基本概 :1进程:一个独立程序的每一次运行称为一个进程。执行进程是指进程里面主线程mian方法开始执行了(静态概念)。机器上运行的都是线程2线程是一个程序不同的执行路径 是一个程序内部的顺序控制流)main方法:一个主线程,主分支3一个时间点上一个CPU只能有一个线程执行进程与线程区别每个进程都有独立的代码和数据空间,进程间的切换会有很大开销。线程可以看成轻量级的进程 同一类线程共享代码和数据空间,每个线程有独立的运行栈个程序计数器,线程切换开销小。多线程:在操作系统中能同时运行多个任务(程序)。多线程:在同一个应用程序中有多个顺序流同时执行。二、 线程的创建和启动1实现Runnable接口(常用)设计一个实现Runable接口的类,根据需要重写run方法;建立该类的对象,以此对象为参数建立Thread类的对象;调用Thread类对象start方法启动线程,将执行权转交到run方法。2继承Thread类 定义一个从Thread类继承的子类并重写其run方法然后生成该类的对象,调用Thread类对象start方法启动线程说明:Runnable接口 java.lang.Runnable Java多线程机制的一个重要部分,实际上它只有一个run()方法 Thread类实现了Runnable接口,相对于Thread类,它更适合于多个线程处理同一资源 实现Runnable接口的类的对象可以用来创建线程,这时start方法启动此线程就会在此线程上运行run()方法 在编写复杂程序时相关的类可能已经继承了某个基类,而Java不支持多继承,在这种情况下,便需要通过实现Runnable接口来生成多线程Thread类 java.lang.Thread 在Java程序中创建多线程的方法之一是继承Thread类 封装了Java程序中一个线程对象需要拥有的属性和方法 从Thread类派生一个子类,并创建这个子类的对象,就可以产生一个新的线程。这个子类应该重写Thread类的run方法,在run方法中写入需要在新线程中执行的语句段。这个子类的对象需要调用start方法来启动,新线程将自动进入run方法。原线程将同时继续往下执行 Thread类直接继承了Object类,并实现了Runnable接口。它位于java.lang包中,因而程序开头不用import任何包就可直接使用例子:ThreadTestThread1.java 开始使用Eclipse1实现Runnable接口(多线程程序交替执行.多态(接口,常用))package Thread;public class TestThread1 public static void main(String args) Runner r = new Runner();Thread t = new Thread(r);/主线程;t.start();/启动分支线程for(int i=0; i<100; i+) System.out.println("Main Thread:-" + i);class Runner implements Runnable public void run() /线程运行体;for(int i=0; i<100; i+) System.out.println("Runner1 :" + i);2 一般程序先执行子线程,再执行主线程(方法调用)package Thread;public class TestThread1_1 public static void main(String args) Runner1 r = new Runner1();r.run();for(int i=0; i<100; i+) System.out.println("Main Thread:-" + i);class Runner1 implements Runnable public void run() for(int i=0; i<100; i+) System.out.println("Runner1 :" + i);3继承Thread类(继承,不常用)package Thread;public class TestThread1_2public static void main(String arg)Runner1_2 r = new Runner1_2();r.start();for (int i = 0 ;i <= 100; i+)System.out.println("Main Thread:!"+i);class Runner1_2 extends Threadpublic void run()for (int i = 0 ;i <= 100; i+)System.out.println("Runner2:!"+i);2010-4-2 21:04:16 2010-4-14 16:28:59三、 线程状态转换四、 线程控制基本方法Sleep/Join/Yield方法 Sleep/Join(需要捕获异常)例子1 Thread/TestInterrupt.Java (线程结束的方式)package Thread;import java.util.*;public class TestInterrupt public static void main(String arg)MyThread thread = new MyThread();thread.start();tryThread.sleep(10000);/主线程睡眠catch(InterruptedException e)thread.interrupt();/中断线程。class MyThread extends Threadboolean flag = true;public void run()/重写的方法不能抛出不必被重写方法不同的方法,此处不能写throws InterruptedExceptionwhile(flag)System.out.println("-"+ new Date()+"-");trysleep(1000);catch(InterruptedException e)/捕获抛出的异常return;/停止例子2 Thread/ TestJoin.Java (线程合并方式)package Thread;public class TestJoin public static void main(String args) MyThread2 t1 = new MyThread2("abcde"); t1.start();/启动分支线程 try t1.join();/把T1分支线程合并到当前线程 catch (InterruptedException e) for(int i=1;i<=10;i+) System.out.println("i am main thread"); class MyThread2 extends Thread MyThread2(String s) super(s); public void run() for(int i =1;i<=10;i+) System.out.println("i am "+getName(); try sleep(1000); catch (InterruptedException e) return; 例子3 Thread/ TestYield.Java (让出Cup)package Thread;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(); 五、 线程优先级 Priority例子 Thread/ TestPriority.Javapackage Thread;public class TestPriority public static void main(String args) Thread t1 = new Thread(new T1();Thread t2 = new Thread(new T2();t1.setPriority(Thread.NORM_PRIORITY + 3);/提高优先级t1.start();t2.start();class T1 implements Runnable public void run() for(int i=0; i<1000; i+) System.out.println("T1: " + i);class T2 implements Runnable public void run() for(int i=0; i<1000; i+) System.out.println("-T2: " + i);2010年4月14日21:40:41 2010-4-15 16:23:44六、 例子 TestThread2-6TestThread2一个线程类可以启动两个线程package Thread;public class TestThread2 /一个线程类可以启动两个线程public static void main(String args) Runner2 r = new Runner2();Thread t1 = new Thread(r);Thread t2 = new Thread(r);t1.start();t2.start();class Runner2 implements Runnable public void run() for(int i=0; i<30; i+) System.out.println("No. " + i);正常停止线程TestThread4package Thread;public class TestThread4 /怎么正常停止线程public static void main(String args)Runner4 r = new Runner4(); Thread t = new Thread(r); t.start(); for(int i=0;i<i+) if(i%10000=0 & i>0) System.out.println("in thread main i=" + i); System.out.println("Thread main is over"); r.shutDown(); /t.stop(); class Runner4 implements Runnable private boolean flag=true; public void run() int i = 0;while (flag=true) System.out.print(" " + i+); public void shutDown() flag = false; TestThread6 isAlivepackage Thread;public class TestThread6 public static void main(String args)Thread t = new Runner6(); t.start();for(int i=0; i<50; i+) System.out.println("MainThread: " + i); class Runner6 extends Thread public void run() System.out.println(Thread.currentThread().isAlive();for(int i=0;i<50;i+) System.out.println("SubThread: " + i);七、 线程同步引入:两人同时取同一账户的钱两个线程访问同一资源,进程之间协调的问题解决:在进程访问独占资源时先锁定再访问 synchronized 最好只锁定一个对象加锁过程中:一个方法做了同步(加锁)另一个方法没有做同步,别的线程可以访问没做同步的方法,并且能影响已经同步的方法,要保护需要的同步的对象,必须对要访问的对象所有方法要仔细考虑加不加同步,加同步效率变低,不加同步有可能产生数据不一致的后果读写两方法,写的方法加锁。两个方法都改了同一个值,两个方法都应该加同步TsetSync.javapackage Thread;public class TestSync implements Runnable Timer timer = new Timer(); public static void main(String args) TestSync test = new TestSync(); Thread t1 = new Thread(test); Thread t2 = new Thread(test); t1.setName("t1"); t2.setName("t2"); t1.start(); t2.start(); public void run() timer.add(Thread.currentThread().getName();/拿到当前线程的名字 class Timer private static int num = 0; public void add(String name) /public synchronized void add(String name) /synchronized "锁定"关键字 /synchronized (this) /锁定 num +; try Thread.sleep(1); /让线程睡眠,给另一个线程执行的机会,更容易看到xia catch (InterruptedException e) System.out.println(name+", 你是第"+num+"个使用timer的线程"); / t2, 你是第2个使用timer的线程t1, 你是第2个使用timer的线程堆内存:test对象testtimertimer对象t1t2问题出现在线程执行方法时被另一个线程打断了.执行:num +;.System.out.println(name+", 你是第"+num+"个使用timer的线程");两句话时被另个进程打断死锁 07_线程同步_3.aviThread/TestDeadLock.java两个线程锁定了互斥的对象package Thread;/一个线程类模拟两个线程。用flag区分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) /锁定o1try Thread.sleep(500); catch (Exception e) e.printStackTrace();synchronized(o2) /锁定o2System.out.println("1");if(flag = 0) synchronized(o2) /锁定o2try Thread.sleep(500); catch (Exception e) e.printStackTrace();synchronized(o1) /锁定o1System.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();一道面试题:08_线程同步_4.Avi.当m1()方法执行的过程中,另外的线程能执行m2()package Thread;public class TT implements Runnable int b = 100;public synchronized void m1() throws Exceptionb = 1000;Thread.sleep(5000);System.out.println("b = " + b);public void m2() System.out.println(b);public void run() try m1(); catch(Exception e) e.printStackTrace();public static void main(String args) throws Exception TT tt = new TT();Thread t = new Thread(tt);t.start();Thread.sleep(1000);tt.m2();结果:1000b = 1000八、 生产者消费者问题 11_线程同步_7_生产者消费者问题.avi XXX.wait() 让当前访问这个线程等待,此时这个线程的锁不存在了XXXX.notify() 唤醒在此对象监视器上等待的单个线程。一个wait()对应一个notify()package Thread;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 WoTou6;public synchronized void push(WoTou wt) while(index = arrWT.length) try this.wait(); catch (InterruptedException e) e.printStackTrace();this.notifyAll();/ 唤醒arrWTindex = wt;index +;public synchronized WoTou pop() while(index = 0) try this.wait(); catch (InterruptedException e) e.printStackTrace();this.notifyAll();index-;return arrWTindex;class Producer implements Runnable SyncStack ss = null;Producer(SyncStack ss) this.ss = ss;public void run() for(int i=0; i<20; i+) 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+) WoTou wt = ss.pop();System.out.println("消费了: " + wt);try Thread.sleep(int)(Math.random() * 1000); catch (InterruptedException e) e.printStackTrace();2010-4-15 23:17:16Wait和Sleep区别 Wait时别的线程可以访问锁定的对象(调用wait方法的时候必须锁定该对象) Sleep时别的线程不可以访问锁定对象。sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。专心-专注-专业