黑马程序员---------笔记整理(java基础八-----多线程)
来源:互联网 发布:深圳红酒网络销售 编辑:程序博客网 时间:2024/05/16 11:40
---------------------- android培训、java培训、期待与您交流! ----------------------
今天有点晕晕的,说不清的感觉,总觉得时间有点紧,不大够用。不知道究竟是怎么了。慢慢来吧,饭总得一口口吃。尽力!!!来吧,让暴风雨来得更猛烈些吧。
1.1 线程的优势
1.2线程的弊端
1.3 线程和进程的区别
1.4多线程的目的
1.5计算机执行任务的原理
1.6 创建线程的两种方式
1.7 线程的安全问题产生的原因
1.9 线程状态图解
2.0 锁
2.1 死锁
2.2 延迟加载同步代码块儿
2.3 线程间通讯
2.4 同步
2.5 其他
多线程
进程:正在运行中的程序。
线程:就是进程中一个负责程序执行的控制单元(执行路径)
1.1 线程的优势
多线程好处:解决了多部分同时运行的问题
1.2线程的弊端
多线程的弊端:线程太多回到效率的降低,因为线程的执行依靠的是CPU的来回切换。 1.3 线程和进程的区别
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。如果有兴趣深入的话,我建议你们看看《现代操作系统》或者《操作系统的设计与实现》。对就个问题说得比较清楚。
1.4多线程的目的
开启多个线程是为了同时运行多部分代码,每一个线程都有自己运行的 内容,这个内容称为线程要执行的任务
1.5计算机执行任务的原理
应用程序的执行都是cpu在做着快速的切换完成的,而且切换是随机的 1.6 创建线程的两种方式
1.继承Thread。
继承Thread类;覆盖Thread类中的run方法;直接创建Threadde子类对象创建线程;调用start方法开启线程并调用线程的任务run方法。另外可以通过Thread的getName()获取线程的名称。
主要代码:
class ThreadDemo extends Thread{public void run(){for (int i=0;i<10;i++){System.out.println("线程"+getName()+"正在运行:"+i);}}}
class Demo{public static void main(String args[]){ThreadDemo a=new ThreadDemo();ThreadDemo b=new ThreadDemo();a.start();b.start();}}
2.实现runnable接口
定义类实现Runnable接口;
覆盖接口的run的方法,将线程的任务代码封装到run方法中;通过Thread类创建线程对象,将Runnabl接口的子类对象作为Thread类的构造函数的参数进行传递
调用线程对象的start方法开启线程。
主要代码:class RunnableDemo implements Runnable //实现Runnable{public void run(){show();}private void show(){for (int i=1;i<10 ;i++ ){System.out.println(Thread.currentThread().getName()+" "+i);}}}class Demo{public static void main(String[] args){RunnableDemo a=new RunnableDemo();Thread b=new Thread(a); //将任务封装成对象,将其传入线程中Thread b1=new Thread(a);b.start();b1.start();
}}
总结:两种方法的比较:实现Runnable接口,将线程的任务从线程的子类中分离出来的,进行了单独的封装,按照面向对象的思想将任务的封装成对象,避免了java中单继承的局限性。(创建线程第二种方式较好)
1.7 线程的安全问题产生的原因
当一个线程在执行操作共享数据的多条代码过程中,其他线程参与了运算,就会导致线程安全问题的产生。
解决思路:就是将多条操作共享的线程代码封装起来,当有线程在执行这些代码的时候,其他线程就不可以参与运算,执行完以后,
其他的线程才 可以执行。
2.4 同步
同步的好处:解决了线程的安全问题
同步的弊端:相对降低了效率,因为同步外的线程的都会判断同步锁
同步的前提:同步中必须有多个线程并使用同一个锁。
同步的表现:多个线程运行到同步时,谁具备执行权,其他线程就不参与共享数据的操作。
同步代码块儿和同步函数区别:同步函数的锁是固定的this。
状态一,创建,使用start()开启线程。状态二,运行(具备着执行资格,具备着执行权)状态三,冻结(释放执行权,同时释放执行资格)
从运行到冻结的方式:
sleep(time),sleep(time)时间到,进入临时阻塞状态(具备着执行资格,但是不具备执行权,正在等待执行权)
wait()线程等待,notify()线程唤醒,进入临时阻塞状态。
状态四,消亡
从运行到消亡的方式:
2.0 锁stop()中止线程;run()方法结束,线程的任务结束。
2.1 死锁
同步代码块之间的嵌套。就是有两把锁,你那我需要的那把,我持有你需要的那把,而我们谁也不释放该锁,这样
我们都不能进去,在那等待。
主要代码:class DeadLock implements Runnable{public boolean flag=false;public void run(){if (!flag){ while(true){synchronized(this){synchronized(DeadLock.class){System.out.println("true");}}}}else{while(true){synchronized(DeadLock.class){synchronized(this){System.out.println("false");}}}}}}class Test{public static void main(String[] args){DeadLock a=new DeadLock ();Thread t1=new Thread(a);Thread t2=new Thread(a);t1.start();try{ Thread.sleep(10);}catch(Exception e){}a.flag=true;t2.start();}}
2.2 延迟加载同步代码块儿
/*单例设计模式:
//饿汉式。
/*
class Single
{
private static final Single s = new Single();private Single(){}public static Single getInstance(){
return s;
}
}
//懒汉式,请给我写个延迟加载的单例设计模式。
/*区别:懒汉式特点是实例的延迟加载。多线程访问时回出现安全问题。可以加同步来解决。可以用同步代码块或者同步函数。有些低效,用双重判断可以效率问题。同步的时候,用的锁是,该类所属的字节码文件对象。*/
class Single{
private static Single s = null;private Single(){}
public static Single getInstance()
{
if(s==null)
{
synchronized(Single.class)
{
if (s==null)
{
s = new Single();
}
}
}
return s;
}
}class SingleDmeo{
public static void main(String[] args){
System.out.println("Hello World!");
}
}
2.3 线程间通讯
多线程在处理同一资源,但是任务却不同。
1.1 等待唤醒机制:
涉及的方法:
为什么需要唤醒机制:
有时候我们多个线程在操作同一数据时,需要有一个先后顺序,当其中一个线程在操作该数据时,其他线程不能操作该数据,
这时候可能就会涉及到冻结和唤醒机制。
1.2 为什么操作线程的方法wait notify notifyAll 定义在Object类中?
因为这些方法是监视器的方法,监视器其实就是锁,锁可以是任意的对象,任意的对象调用的方法一定定义在Object类当中。
1 .3 线程间通讯最重要的机制:
等待唤醒机制。
1.4 等待唤醒机制中,最常见的体现就是生产者消费者问题:
发现两个问题:1,出现了错误的数据。是因为多生产和多消费的时候,被唤醒的线程没有再次判断标记就执行了。
解决是将if判断变成while判断。
2,发现有了while判断后,死锁了。
因为本方线程唤醒的有可能还是本方线程。所以导致了死锁。
解决:本方必须唤醒对方才有效。notify只能唤醒一个,还不确定。所以干脆唤醒全部,肯定包含对方,
至于被唤醒的本方,会判断标记是否继续等待。
示例代码:class ThreadDemo4{public static void main(String [] args){Resource r = new Resource();Shengchan s = new Shengchan(r);Xiaofei x = new Xiaofei(r);Thread t1 = new Thread(s);Thread t2 = new Thread(s);Thread t3 = new Thread(x);Thread t4 = new Thread(x);t1.start();t2.start();t3.start();t4.start();}}class Resource{private String name;private int count = 1;private boolean flag = false;public synchronized void set(String name){if(flag)try{this.wait();}catch(InterruptedException e){}this.name = name+count;count++;System.out.println(Thread.currentThread().getName()+"...生产者...."+this.name);flag = true;notify();}public synchronized void out(){if(!flag)try{this.wait();}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+".........消费者........."+this.name);flag = false;notify();}}class Shengchan implements Runnable{Resource r;Shengchan(Resource r){this.r = r;}public void run(){while(true)r.set("烤鸭");}}class Xiaofei implements Runnable{Resource r;Xiaofei(Resource r){this.r = r;}public void run(){while(true)r.out();}}编译后:
造成了线程的不安全的问题。
notify唤醒的是不确定的一其中的一个线程,造成了生产出的烤鸭没有被消费。
解决多生产多消费的线程安全问题:示例代码:class ThreadDemo4{public static void main(String [] args){Resource r = new Resource();Shengchan s = new Shengchan(r);Xiaofei x = new Xiaofei(r);Thread t1 = new Thread(s);Thread t2 = new Thread(s);Thread t3 = new Thread(x);Thread t4 = new Thread(x);t1.start();t2.start();t3.start();t4.start();}}class Resource{private String name;private int count = 1;private boolean flag = false;public synchronized void set(String name){while(flag) //这里写while循环是为了当线程每次醒后再判断一次标记。try{this.wait();}catch(InterruptedException e){}this.name = name+count;count++;System.out.println(Thread.currentThread().getName()+"...生产者...."+this.name);flag = true;notifyAll();}public synchronized void out(){while(!flag)try{this.wait();}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+".........消费者........."+this.name);flag = false;notifyAll();}}class Shengchan implements Runnable{Resource r;Shengchan(Resource r){this.r = r;}public void run(){while(true)r.set("烤鸭");}}class Xiaofei implements Runnable{Resource r;Xiaofei(Resource r){this.r = r;}public void run(){while(true)r.out();}}
1.5 同步代码块儿
同步代码块,对于锁的操作是隐式的
1.6 Lock接口
出现替代了同步代码块或者同步函数。将同步的隐式锁操作编程了显示锁操作。 同事更为灵活。可以一个锁上加上多组监视器。
1.7Condition接口
出现替代了Object中的wait notify notifyAll方法。
1.8 停止线程:
1,stop方法
class StopThread implements Runnable{
private boolean flag = true;public synchronized void run(){
while(flag){
try {
wait();//t0 t1
}catch (InterruptedException e){
System.out.println(Thread.currentThread().getName()+"....."+e);
flag = false;
}
System.out.println(Thread.currentThread().getName()+"......++++");
}
}
public void setFlag(){
flag = false;
}}
class StopThreadDemo
{
public static void main(String[] args) {
StopThread st = new StopThread();
Thread t1 = new Thread(st);Thread t2 = new Thread(st);t1.start();t2.setDaemon(true);t2.start();int num = 1;
for(;;){
if(++num==50){
//st.setFlag();
t1.interrupt();//t2.interrupt();break;
}
System.out.println("main...."+num);
}System.out.println("over");
}
}
面试题
class Test implements Runnable
{
public void run(Thread t)
{}
}
//如果错误 错误发生在哪一行?错误在第一行,应该被abstract修饰
class ThreadTest
{
public static void main(String[] args)
{
new Thread(new Runnable(){
public void run(){
System.out.println("runnable run");
}}){
public void run(){
System.out.println("subThread run");}
}.start();
打印的是subThread run 运行以子类的为主,如果子类里面没有这个run()方法的话,就以任务线程的run为主,如果都没有的话,以父类自己的为主。
总结:
wait和sleep的区别:
wait可以指定时间也可以不指定.
sleep必须指定时间。
在同步中时,对于CPU的执行权和锁的处理不同。
wait:释放执行权,释放锁。
sleep:释放执行权,不释放锁。
wait方法,必须定义在同步中,sleep不一定。
-
--------------------- android培训、java培训、期待与您交流! ----------------------
- 黑马程序员---------笔记整理(java基础八-----多线程)
- 黑马程序员---JAVA基础---多线程(八)
- 笔记整理(java基础八-----多线程)
- 黑马程序员——Java基础视频笔记(八):多线程编程
- 黑马程序员---------笔记整理(java基础六-----异常)
- 黑马程序员-----笔记整理(java基础十----集合)
- 黑马程序员-----八、java基础多线程技术总结一
- JAVA学习笔记整理八(多线程)
- 黑马程序员--- 笔记整理(java基础七-----问题整理)
- 黑马程序员 JAVA基础 - 多线程(一)
- 黑马程序员 JAVA基础--多线程(二)
- Java基础---多线程 (黑马程序员)
- 黑马程序员--Java基础--多线程(一)
- 黑马程序员--Java基础--多线程(二)
- 黑马程序员-----java基础(多线程)
- 黑马程序员---Java基础(多线程)
- 黑马程序员-java基础(五)-多线程
- 黑马程序员——Java基础-整理笔记
- 一个走迷宫的程序
- hdu 1032 The 3n + 1 problem
- 双色球手机版 旋转矩阵手机版
- 黑马程序员--- 笔记整理(java基础七-----问题整理)
- 根据iphone3/ios5开发基础教程-录制ios视频基础教程-视频下载专辑/反馈
- 黑马程序员---------笔记整理(java基础八-----多线程)
- MFC进度条同步问题
- 与人来往时关注内容而不是表情为人处世智慧人生
- 一个技术工作者的四大核心价值理念
- Informix 各版本bug及补丁下载URL
- JSP自定义标签开发入门
- 我的WEB SERVER 1.0
- MyEclipse的注册码破解
- [最小点基]LightOJ 1034 - Hit the Light Switches