首页 马士兵 J2SE第九章 线程 个人学习笔记

马士兵 J2SE第九章 线程 个人学习笔记

举报
开通vip

马士兵 J2SE第九章 线程 个人学习笔记马士兵 J2SE第九章 线程 个人学习笔记 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce 第九章 Java多线程机制 线程基本概念 Runnable线程类接口 线程创建和启动 线程的调度好优先级 线程的状态控制 sleep join yield 线程同步synchronized wait notify/notifyAll 一、 线程基本概 : 1进程:一个独立程序的每一次运行称为一个进程。 执行进程是...

马士兵 J2SE第九章 线程 个人学习笔记
马士兵 J2SE第九章 线程 个人学习笔记 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce 第九章 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方法启动线程 1 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce 说明: 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 任何包就可直接使用 例子:Thread\TestThread1.java 开始使用Eclipse 1实现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 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce } } } 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_2{ public 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 Thread{ public 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 三、 线程状态转换 3 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce FromJava Web开发详解 四、 线程控制基本方法 Sleep/Join/Yield方法 Sleep/Join(需要捕获异常) 例子1 Thread/TestInterrupt.Java (线程结束的方式) package Thread; import java.util.*; public class TestInterrupt { public static void main(String arg[]){ 4 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce MyThread thread = new MyThread(); thread.start(); try{Thread.sleep(10000);}//主线程睡眠… catch(InterruptedException e){} thread.interrupt();//中断线程。 } } class MyThread extends Thread{ boolean flag = true; public void run(){//重写的方法不能抛出不必被重写方法不同的方法,此处不能写throws InterruptedException while(flag){ System.out.println("----"+ new Date()+"----"); try{ sleep(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); 5 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce } 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.Java package 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(); } } 6 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce 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-6 TestThread2一个线程类可以启动两个线程 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); } } } 正常停止线程TestThread4 package 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<100000;i++){ if(i%10000==0 & i>0) System.out.println("in thread main i=" + i); } 7 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce 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 isAlive package 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 最好只锁定一个对象 加锁过程中:一个方法做了同步(加锁)另一个方法没有做同步,别的线程可以访问没做同步的方法,并且能影响已 经同步的方法,要保护需要的同步的对象,必须对要访问的对象所有方法要仔细考虑加不加同步,加同步效率变低, 不加同步有可能产生数据不一致的后果 读写两方法,写的方法加锁。 两个方法都改了同一个值,两个方法都应该加同步 8 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce TsetSync.java package 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 ++; xia try {Thread.sleep(1);} //让线程睡眠,给另一个线程执行的机会,更容易看到 catch (InterruptedException e) {} System.out.println(name+", 你是第"+num+"个使用timer的线程"); //} } } t2, 你是第2个使用timer的线程 t1, 你是第2个使用timer的线程 堆内存:test对象 test timer t1 t2 timer对象 问题出现在线程执行方法时被另一个线程打断了. 执行: num ++; ..... 9 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce System.out.println(name+", 你是第"+num+"个使用timer的线程"); 两句话时被另个进程打断 死锁 07_线程同步_3.avi Thread/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) {//锁定o1 try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } synchronized(o2) {//锁定o2 System.out.println("1"); } } } if(flag == 0) { synchronized(o2) {//锁定o2 try { Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } synchronized(o1) {//锁定o1 System.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(); 10 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce } } 一道面试题:08_线程同步_4.Avi.当m1()方法执行的过程中,另外的线程能执行m2() package Thread; public class TT implements Runnable { int b = 100; public synchronized void m1() throws Exception{ b = 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(); } } 结果: 1000 b = 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(); 11 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce 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 WoTou[6]; public synchronized void push(WoTou wt) { while(index == arrWT.length) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll();// 唤醒 arrWT[index] = wt; index ++; } public synchronized WoTou pop() { while(index == 0) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.notifyAll(); index--; return arrWT[index]; } 12 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce } 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:16 Wait和Sleep区别 Wait时别的线程可以访问锁定的对象(调用wait方法的时候必须锁定该对象) Sleep时别的线程不可以访问锁定对象。 sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持, 到时后会自动恢复。调用sleep不会释放对象锁。 wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针 对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 13 尚学堂科技_马士兵_JAVA视频教程_J2SE_5.0_第09章_线程 听课笔记 2010-4-2 20:16:34 by LoveXForce 14
本文档为【马士兵 J2SE第九章 线程 个人学习笔记】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_037433
暂无简介~
格式:doc
大小:137KB
软件:Word
页数:0
分类:互联网
上传时间:2017-09-21
浏览量:9