黑马程序员-------java基础------多线程
来源:互联网 发布:mac百度搜索历史 编辑:程序博客网 时间:2024/05/18 02:59
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
java基础知识-----多线程
引言
理解线程,先要理解进程。
1.进程
一个正在执行的程序,每一个执行程序都有一个执行顺序又叫控制单元。
2.线程
每一个控制单元就是线程。
3.多线程
jvm启动时,有一个java.exe的进程,该进程中至少有一个线程执行。
而该线程执行的代码在main方法中--主线 程。 jvm中除了有主线程还有 一个负责垃圾回收的线程。
像这种在一个程序中有多个线程执行的方式称为多线程。
4.多线程的意义在哪?
让线程产生同时运行的效果,提高运行效率。
5.cpu运行原理
1) 每一次运行效果不同源自其随机性。多个线程都在获取执行权,谁得到执行,谁就运行。运行多久,cpu决定。
2)为什么会有同时执行效果?在同一时刻,只能有一个程序执行,之所以会有同时执行的效果是因为cpu在多个进 程之间做着快速的切换。
一、线程的创建
创建有两种方式
1. 继承Thread方式
1)定义类集成Thread -------class Demo extends Thread
2)复写run方法----------------public void run()
3)调用start方法开启线程-----demo d = new demo(); d.start();
注意只能用start方法,因为调用start会自动找run方法需要被执行的代码。进行线程开启。
而d.run()只是进行了run方法的调用。,不是开启线程。
//继承的方式创建线程class Demo extends Thread{DemoName(String name){super(name);} //复写方法public void run(){ // 此处放执行代码for(int i=1;i<40;i++){System.out.println(Thread.currentThread().getName()+"run"+i);}}}class Demo1{ public static void main(String[] args) { //创建线程 Demo d1 = new Demo(); Demo d2 = new Demo(); //开启线程,调用start方法 d1.start(); d2.start(); }}
2.实现Runnable接口
1)定义类实现Runnable接口-------class demo implements Runnable
2)覆盖Runnable中的run方法-------public void run()
3)创建线程对象---------------------Thread t = new Thread();
3) 创建Runnable接口子类对象-----demo d = new demo();
作为参数传递给Thread的构造函数,见上步。
4)调用start方法 -------------------t.satrt();
为什么将Runnabl子类对象作为参数进行传递?
因为因定义的run方法所属的对象时Runnable子类对象,所以要让线程去指定对象的run方法,
就必须明确该run方法所属的对象。
//用实现的方式创建线程class Demo implements Runnable{private int ticket = 20;Object obj = new Object(); //复写run方法public void run(){synchronized(obj)//进行同步处理{while(true){if(ticket>0){ //异常处理方式try{Thread.sleep(10);}catch (Exception e){ System.out.println(e.toStrig());}System.out.println(Thread.currentThread().getName());}}}}}class Demo2{public static void main(String[] args) {Demo d = new Demo(); //创建线程Thread d1 = new Thread(d);Thread d2 = new Thread(d);Thread d3 = new Thread(d); //线程启动,调用start()方法d1.start();d2.start();d3.start();}}
实现与继承的区别
实现:线程代码写在Runnab接口子类的run方法中。
继承:线程代码写在Thread子类run方法中
实现的好处
避免了单继承的局限性。建议使用。java只有单继承,没有多继承。
二、线程运行状态
run结束,消亡
|stop
被创建--------------------->运行<--(notify、notifyAll)------(wait、sleep)------>冻结
|
临时阻塞:具备执行资格,但没有执行权
1.线程运行中出现的安全问题
多条语句操作一个线程共享数据时,一个线程执行了一部分,还没执行完,另一个线程就参与执行,导致共享数据的错误。
2.对于安全问题java提供的解决方案
---同步代码块
synchronized(对象)
{
同步代码
}
3.解决的原理
保证同步中只有一个线程进行。加锁
好处
解决了多线程的安全问题。
弊端
多个线程要判断锁,耗费资源
-------------》加锁的前提:
1)有2个或2个以上的线程
2)多个线程要共用一个锁
4.扩展
1) 同步的表现形式
同步代码块
Object obj = new Object();
public void add(int n)
{
synchronized(obj)
{
同步代码;
}
}
2)同步函数
public synchronized void add(int n)
{
}
同步函数的锁是this,被对象调用,就有一个所属对象的引用
当为静态同步函数时,锁是所属类对应的字节码文件 Class对象
public static synchronized void add(int n)
{
synchronized(Ticjet.class)
{
同步执行代码
}
}
锁不是this,为什么?
静态函数中不能定义this,静态static进入内存时,没有本类对象,但必有该类对应的字节码文件.class
5.死锁
2个或者2个以上的进程在执行过程中,因为争夺资源而出现的一种相互等待的状态。
若无外力作用,则无法进行下去,则称系统处于死锁状态,或者系统产生了死锁。
当同步中嵌套同步时有可能出现死锁现象。
要会写一个死锁程序
class Test implements Runnable{private boolean flag;Test(boolean flag){this.flag = flag;}public void run(){if(flag){while(true){synchronized(MyLock.locka){System.out.println("----if locka");synchronized(MyLock.lockb){System.out.println("---if lockb");}}}}else{ while(true){synchronized(MyLock.lockb){System.out.println("---else lockb");synchronized(MyLock.locka){System.out.println("---else locka");}}}}}class MyLock{static Object locka = new Object();static Object lockb = new Object();}class DeadLockTest{public static void main(String[] args) {Thread t1 = new Thread(new Test(true));Thread t2 = new Thread(new Test(false));t1.start();t2.start();}}
6.利用锁的单利设计模式
1)饿汉式
class Single { private finale Single s = new Single(); private Single(){} public static Single getInstance() { return s; } }
2)懒汉式-------加锁
class Single { private Single s = null; private Single(){} public static synchronized Single getInstance() { if(s==null) { synchronized(Single.class) { if(s==null) s = new Single(); } } return s; } }
三、线程间通信
1.线程间通信
多个线程操作同一个资源,但操作动作不同。
当某些代码需要被同事执行时,用单独的线程进行封装。
/*需求:买票程序多个窗口同时买票*/class Ticket implements Runnable //实现Runnable接口好处:避免单继承的局限性{private int tick = 100;Object obj = new Object();//Object为所有类的子类,无需定义public void run(){ //synchronized内放任意对象,synchronized(obj)//同步代码块,{}内放需要被同步的代码 { //哪些被同步,就哪些操作共享数据while(true) { if(tick>0){try{Thread.sleep(10);}catch(Exception e ){}//此行代码可以显示出不安全数据System.out.println(Thread.currentThread().getName()+"sale :"+tick--); } }}}}class maipiao2{public static void main(String[] args) {Ticket t = new Ticket();Thread t1 = new Thread(t);//实现Runnable语句 new Thread(对象p);Thread t2 = new Thread(t);Thread t3 = new Thread(t);Thread t4 = new Thread(t); t1.start();t2.start();t3.start();t4.start();}}
/*需求银行有一个金库有两个储户分别存300元,每次存100,存3次目的:该程序是否有安全问题,如果有,如何解决?如何找问题:1.明确哪些代码是多线程运行代码2.明确共享数据3.明确多线程运行代码中哪些语句是操作共享数据的*/class Bank{private int sum;public void add(int n){sum=sum+n;System.out.println("sum="+sum);}}class Cus implements Runnable{Bank b = new Bank();public void run(){for(int i=0;i<3;i++){b.add(100);}}}class tongbuhanshu{public static void main(String[] args) {Cus c = new Cus();Thread t1 = new Thread(c);Thread t2 = new Thread(c);Thread t3 = new Thread(c);t1.start();t2.start();t3.start();}}
2.等待唤醒机制
均使用在同步中,因为要对持有锁的线程操作,只有同步有锁。
操作方法定义在Object中
原因:
操作方法都在同步中,要使用这些方法必须要标示所属的同步锁。
而且只可被同一锁唤醒,锁又可以是任意对象,任意对象调用的方法
一定在Object方法中。
3.sleep与wait的区别
wait():等待,释放执行权,释放锁
sleep():释放执行权,不释放锁。
4.为什么定义notifyAll()
因为在唤醒对方线程时,如果使用notify,容易出现只唤醒本线程的情况,
导致程序中所有线程都等待。
5.jdk1.5后,停止线程的方法
1) 停止线程的一般方法
一般情况,有一个
run()
{
while(flag)
{
执行代码
}
}
只要在main方法,该线程执行一段时间,将flag进行标记为false,则线程就结束
2)特殊情况
线程处于冻结状态,不会读取到标记,就不会结束,
当没有指定的方式让冻结的线程恢复到正常运行状态当中时,
就需要对冻结进行强制解除,强制恢复到正常运行状态。
此时就可以读取标记,结束线程。------Thread -----interrupt
6.扩展
1)join方法
临时加入线程执行,当A执行到B的join时,A等待,B进行执行。
当B执行完后,A再进行执行。
2)守护线程
又叫后台线程
Thread.setDaemon(true);线程启动之前
启动后与前台线程共同抢cpu执行权,当所有前台都结束后,后台自动结束。
3)setPriority(Thread.MAX_PRIORITY);
设置线程优先级。
MAX_PRIORITY 最高级10级
MIN_PRIORITY 最低级 1级
NORM_PRIORITY 默认优先级5级
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
0 0
- 黑马程序员 Java基础 --->多线程
- 黑马程序员--java基础多线程
- 黑马程序员JAVA基础-多线程
- 黑马程序员---java基础多线程
- 黑马程序员--java基础--多线程
- 黑马程序员--Java基础--多线程
- 黑马程序员-----java基础 多线程
- 黑马程序员-->Java基础-->多线程
- 黑马程序员-------java基础------多线程
- 黑马程序员--JAVA基础---多线程
- 黑马程序员--Java基础--多线程
- 黑马程序员---Java基础---多线程
- 黑马程序员---java基础--多线程
- 黑马程序员-Java基础-多线程
- 黑马程序员-----------JAVA基础----多线程
- 黑马程序员<java基础<多线程>>
- 黑马程序员-【java基础】-多线程
- 黑马程序员--java基础--多线程
- JQuery鼠标移动上去显示预览图
- Qtcreator中文输入法不能使用问题
- WEB界面客制化之采购申请审批界面(改OAF的VO.XML文件-上传-重启应用-个性化添加栏位)
- javascript的fn方法
- GNU-makefle (一) 基本介绍
- 黑马程序员-------java基础------多线程
- POJ_3667 线段树+lazy (线段树经典题)
- mongoDB的基本操作以及数据的导入导出,备份和恢复
- 测试感想
- CF 479D Long Jumps
- UVA - 10066 The Twin Towers(dp+最大公共子序列)
- ThinkPHP教程--8--之配置格式
- VIM 标签页 (tab)
- Aromafm移植到Android recovery以开发GUI的实现