黑马程序员技术交流社区

标题: 多线程整理 [打印本页]

作者: 七丶哥    时间: 2014-9-1 22:12
标题: 多线程整理
多线程
static Thread.currentThread(); 获取当前线程对象
this.getName();  获取线程名称
setName ; 设置线程名称

1.定义类实现Runnable接口
2.覆盖Runnbale接口中的run方法,将线程要运行的代码存放在该run方法中。
3.通过Thread类建立线程对象
4.将Runnbale接口的子类对象作为实际参数传递给Thread类的构造函数
为什么要将Runnable接口的子类对象传递给Thread的构造函数,因为,自定义的run方法所属的对象是Runnable接口的子类对象。所以要让线程去指定对象的run方法,就必须明确该run方法所属的对象。
5.调用Thread类的start方法开启线程并调用Runnable接口子类的run方法


实现方式好处:避免了单继承的局限性。在定义线程时,建议使用实现方式。

两种方式区别:
继承Thread:线程代码存放Thread子类run方法中。
实现Runnable,线程代码存放在接口的子类的run方法。

通过分析发现多线程的运行出现了安全问题,问题的原因:当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没执行完,另一个线程参与进来执行,导致共享数据的错误。
解决办法:
对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行
java对于多线程的安全问题提供了专业的解决方式。就是同步代码块。synchronized(对象){需要被同步的代码}
对象如同锁。持有锁的线程可以在同步中执行,没有只有锁的线程即使获取了cpu的执行权也进不去,因为没有锁。
火车上的卫生间--经典。
同步的前提:
1.必须要有两个或者两个以上的线程。
2.必须是多个线程使用同一个锁。必须保证同步中只能有一个线程在运行。
好处:解决了多线程的安全问题。
弊端:多个线程需要判断锁,较为消耗资源。
同步有两种变现形式
同步代码块
同步函数

同步函数用的是那一个锁呢?
函数需要被对象调用。那么函数都有一个所属对象引用,就是this.所以同步函数使用的锁就是this.
如果同步函数被静态修饰后,使用的锁是什么呢?通过验证,发现不在是this.因为静态方法中也不可以定义this。静态进内存时,内存中没有本来对象,但是一定有该类对应的字节码文件对象。类名.class   该对象的类型是Class
静态的同步方法,使用的锁是该方法所在类的字节码文件对象。类名.class
//懒汉式  延迟加载  如果多线程会出现安全问题 需要双重判断,  锁里面的对象是该类所属的字节码文件
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 SingleDemo{
        public static void main(String[] args){
               
        }
}

死锁:
你持有一个锁,我持有一个锁,我到你那里运行,要拿你的锁,你要到我里面运行,要拿我的锁,你也不给锁,我也不让锁,程序就挂了,产生死锁。
同步中嵌套同步,而锁却不同

线程间通信:
其实就是多个线程在操作同一个资源,但是操作的动作不同。

等待唤醒机制:
class Res{
        String name;
        String sex;
        boolean flag = false;
}
class Input implements Runnable{
        private Res r;
        Input(Res r){
                this.r = r;
        }
        public void run(){
                int x = 0;
                while(true){
                        synchronized(r){
                                if(r.flag){
                                        try(r.wait();}catch(Exception e){}
                                        if(x==0){
                                                r.name = "mike";
                                                r.sex = "man";
                                        }else{
                                                r.name = "丽丽";
                                                r.sex = "女女";
                                        }
                                        x = (x+1)%2;
                                        r.falg =true;
                                        r.notify();
                                }
                        }
                }       
        }
}
class Output implements Runnable{
        private Res r;
        Output(Res r){
                this.r = r;
        }
        public void run(){
                while(true){
                        synchronized(r){
                                if(!r.flag){
                                        try(r.wait();}catch(Exception e){}
                                        System.out.println(r.name+"..."+r.sex);
                                        r.flag = false;
                                        r.notify();
                                }
                        }
                }
        }
}


notifyAll();
wait
notify
notifyAll
都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才具有锁。为什么这些操作线程的方法要定义在Object类中呢?因为这些方法在操作同步中线程时,都必须要标识它们所操作线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒,不可以对不同锁中的线程进行唤醒。也就是说等待和唤醒必须是同一个锁。而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。


作者: 赵哲成    时间: 2014-9-2 00:33
谢谢分享!!!
作者: 冯大卫    时间: 2014-9-2 00:36
多谢楼主分享
作者: 君行    时间: 2014-9-2 02:14
楼主太给力了
作者: 想做开发    时间: 2014-9-2 12:03
哎  有老师带着果然好啊
作者: Apologize丶    时间: 2014-9-2 12:53
谢谢分享,这快一直理解的不好
作者: 粺¹³¼畅    时间: 2014-9-2 13:23
顶!!!!!!!!!!!!
作者: king13131313    时间: 2014-9-2 13:45
谢分享!!
作者: xpsyztd    时间: 2014-9-2 14:04
感谢分享
作者: zhuohong_xiao    时间: 2014-9-2 14:58
理解的好透彻啊。
作者: zhxu188    时间: 2014-9-2 16:04
楼主是一个有心人,整理的不错

作者: 不服™け你咬我    时间: 2014-9-2 17:31
好详细,,谢谢楼主分享
作者: MeryStyle    时间: 2014-9-2 19:57
多谢分享!!
作者: ItJack    时间: 2014-9-3 10:35
谢谢楼主分享,讲的很详细。
作者: ╃→梅飛揚之城    时间: 2014-9-3 10:54
非常好,收下
作者: wfaly    时间: 2014-9-3 11:43
谢谢 楼主 分享....
作者: 大山    时间: 2014-9-3 12:11
楼主乃牛人也
作者: sunny~    时间: 2014-9-3 12:43
嗯嗯~~~~~
作者: 范鹏霄    时间: 2014-9-3 12:49
多谢分享
作者: alexchy    时间: 2014-9-3 13:24
楼主整理的好




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2