Java多线程与并发库高级应用

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

张孝祥_Java多线程与并发库高级应用【视频介绍:】Java线程是一项非常基本和重要的技术,在偏底层和偏技术的Java程序中不可避免地要使用到Java线程技术,特别是android手机程序和游戏开发中,多线程成了必不可少的一项重要技术。但是,很多Java程序员对Java线程技术的了解都仅停留在初级阶段,在项目中一旦涉及到多线程时往往就表现得糟糕至极,所以,软件公司常常使用Java线程技术来考察面试者的基本功和判断其编码水平的高低。本套视频教程是专门为了帮助那些已经学习和了解过、但掌握得并不是很深入的人们提高java线程技术而讲解的,所以,Java线程初学者学习本视频教程时可能会比较吃力,可能必须耐心学习多遍才能渐入佳境,但是,你一旦掌握了其中的内容,你对Java线程技术的了解将会相当出众!【视频目录列表:】01.传统线程技术回顾02.传统定时器技术回顾03.传统线程互斥技术04.传统线程同步通信技术05.线程范围内共享变量的概念与作用06.ThreadLocal类及应用技巧07.多个线程之间共享数据的方式探讨08.java5原子性操作类的应用09.java5线程并发库的应用10.Callable与Future的应用11.java5的线程锁技术12.java5读写锁技术的妙用13.java5条件阻塞Condition的应用14.java5的Semaphere同步工具15.java5的CyclicBarrier同步工具16.java5的CountDownLatch同步工具17.java5的Exchanger同步工具18.java5阻塞队列的应用19.java5同步集合类的应用20.空中网挑选实习生的面试题121.空中网挑选实习生的面试题222.空中网挑选实习生的面试题323.源代码与资料01.传统线程技术回顾传统是相对于JDK1.5而言的传统线程技术与JDK1.5的线程并发库线程就是程序的一条执行线索/线路。创建线程的两种传统方式1.创建Thread的子类,覆盖其中的run方法,运行这个子类的start方法即可开启线程Threadthread=newThread(){@Overridepublicvoidrun(){while(true){获取当前线程对象获取线程名字Thread.currentThread()threadObj.getName()让线程暂停,休眠,此方法会抛出中断异常InterruptedExceptionThread.sleep(毫秒值);}}};thread.start();2.创建Thread时传递一个实现Runnable接口的对象实例Threadthread=newThread(newRunnable(){publicvoidrun(){}});thread.start();问题:下边的线程运行的是Thread子类中的方法还是实现Runnable接口类的方法newThread(b、传递实现Runnable接口的对象newRunnable(){publicvoidrun(){}}){a、覆盖Thread子类run方法publicvoidrun(){}}.start();分析:newThread(Runnable.run()){run()}.start();子类run方法实际就是覆盖父类中的run方法,如果覆盖了就用子类的run方法,不会再找Runnable中的run方法了,所以运行的是子类中的run方法总结:由Thread类中的run方法源代码中看出,两种传统创建线程的方式都是在调用Thread对象的run方法,如果Thread对象的run方法没有被覆盖,并且像上边的问题那样为Thread对象传递了一个Runnable对象,就会调用Runnable对象的run方法。多线程并不一定会提高程序的运行效率。举例:一个人同时在三张桌子做馒头多线程下载:并不是自己电脑快了,而是抢到更多服务器资源。例:服务器为一个客户分配一个20K的线程下载,你用多个线程,服务器以为是多个用户就分配了多个20K的资源给你。02.传统定时器技术回顾传统定时器的创建:直接使用定时器类Timera、过多长时间后炸newTimer().schedule(TimerTask定时任务,Datetime定的时间);b、过多长时间后炸,以后每隔多少时间再炸newTimer().schedule(TimerTask定时任务,Long延迟(第一次执行)时间,Long间隔时间);TimerTask与Runnable类似,有一个run方法Timer是定时器对象,到时间后会触发炸弹(TimerTask)对象示例:newTimer().schedule(newTimerTask()定时执行的任务{publicvoidrun(){SOP(“bombing”);}显示计时信息while(true){SOP(newDate().getSeconds());Thread.sleep(1000);}},10定好的延迟时间,10秒以后执行任务);问题:2秒后炸,爆炸后每隔3秒再炸一次定时器2秒后炸,炸弹里还有定时器(每3秒炸一次)classMyTimerTaskextendsTimerTask这就是准备用的子母弹{publicvoidrun(){本身就是一颗炸弹SOP(bombing);内部子弹newTimer().schedule(newMyTimerTask(),2000);}}放置子母弹,2秒后引爆newTimer().schedule(newMyTimerTask(),2000);问题延伸:上面的问题延伸,母弹炸过后,子弹每隔3秒炸一次,再每隔8秒炸一次1、在MyTimerTask内部定义一个静态变量记录炸弹号,在run方法内将炸弹号加1,每次产生新炸弹,号码就会加1,根据炸弹号判断是3秒炸还是8秒炸。注意:内部类中不能声明静态变量定义一个静态变量privatestaticcount=0;在run方法内部:count=(count+1)%2;将定时器的时间设置为:2000+2000*count2、用两个炸弹来完成,A炸弹炸完后启动定时器安装B炸弹,B炸弹炸完后也启动一个定时器安装A炸弹。定时器还可以设置具体时间,如某年某月某日某时……可以设置周一到周五做某事,自己设置的话需要换算日期时间,可以使用开源工具quartz来完成。03.传统线程互斥技术线程安全问题例子:银行转账同一个账户一边进行出账操作(自己交学费),另一边进行入账操作(别人给自己付款),线程不同步带来的安全问题示例:逐个字符的方式打印字符串classOutputer{publicvoidoutput(Stringname){intlen=name.length();for(inti=0;ilen;i++)SOP(name.charAt(i));逐个字符打印SOP();换行}}publicvoidtest(){Outputeroutputer=newOutputer();newThread(newRunnable(){publicvoidrun(){Thread.sleep(100);outputer.output(“zhangxiaoxiang”);}}).start();newThread(newRunnable(){publicvoidrun(){Thread.sleep(100);outputer.output(“lihuoming”);}}).start();}注意:内部类不能访问局部变量,要访问需加final静态方法中不能创建内部类的实例对象打印结果发现的问题:线程不同步所致,两个线程都在使用同一个对象要避免下边产生的问题,左边方法体中的代码要实现原子性有一个线程正在使用这个方法的代码,别的线程就不能再使用。就和厕所里的坑一样,已经有人在用了,别人就不能再去用了。Java中某段代码要实现排他性,就将这段代码用synchronized关键字保护起来。同步锁可以用任意对象,相当于门锁synchronized(name){for(inti=0;ilen;i++)SOP(name.charAt(i));逐个字符打印SOP();换行}这样的话,有一个线程进入保护区域后,没出来的话,别的线程就不能进入保护区域。要实现互斥,在这个位置必须使用同一个对象使用name就达不到同步效果使用output对象即可达到同步效果互斥方法:a、同步代码块synchronized(lock){}b、同步方法方法返回值前加synchronized同步方法上边用的锁就是this对象静态同步方法使用的锁是该方法所在的class文件对象使用synchronized关键字实现互斥,要保证同步的地方使用的是同一个锁对象publicsynchronizedvoidoutput(Stringname){intlen=name.length();这里就不要再加同步了,加上极易出现死锁for(inti=0;ilen;i++)SOP(name.charAt(i));逐个字符打印SOP();换行}04.传统线程同步通信技术面试题,子线程10次与主线程100次来回循环执行50次下面是我刚看完面试题就暂停视频自己试着写的代码,还可以,结果完成要求了在单次循环结束后让这个刚结束循环的线程休眠,保证另一个线程可以抢到执行权。publicclassThreadInterViewTest{/***刚看到面试题没看答案之前试写*子线程循环10次,回主线程循环100次,*再到子线程循环10次,再回主线程循环100次*如此循环50次*/publicstaticvoidmain(String[]args){intnum=0;while(num++50){newThread(newRunnable(){@Overridepublicvoidrun(){circle(子线程运行,10);}}).start();try{//加这句是保证上边的子线程先运行,刚开始没加,主线程就先开了Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}circle(主线程,100);}}publicstaticsynchronizedvoidcircle(Stringname,intcount){for(inti=1;i=count;i++){System.out.println(name+::+i);}try{Thread.sleep(5000);}catch(InterruptedExceptione){e.printStackTrace();}}}张老师讲的方法:1、将子线程和主线程中要同步的方法进行封装,加上同步关键字实现同步2、两个线程间隔运行,添加一个标记变量进行比较以实现相互通信,加色的部分waitnotifynotifyAllwait会抛出异常classBusiness{privatebooleanbShouleSub=true;publicsynchronizedvoidsub(){if(bShouleSub){for(inti=1;i11;i++)SOP(sub+i);bShouldSub=false;this.notify();}elsethis.wait();}publicsynchronizedvoidmain(){if(!bShouldSub){for(inti=1;i101;i++)SOP(main+i);bShouldSub=true;this.notify();}elsethis.wait();}}经验:要用到共同数据(包括同步锁)或相同算法的多个方法要封装在一个类中锁是上在代表要操作的资源类的内部方法中的,而不是上在线程代码中的。这样写出来的类就是天然同步的,只要使用的是同一个new出来的对象,那么这个对象就具有同步互斥特性判断唤醒等待标记时使用while增加程序健壮性,防止伪唤醒05.线程范围内共享变量的概念与作用线程范围内共享数据图解:

1 / 42
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功