您的位置:首页 > 职场人生

黑马程序员之java多线程

2014-03-09 10:56 197 查看
-------
android培训、java培训、期待与您交流! ----------

进程:是一个正在执行的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。

线程:就是进程中的一个独立控制单元,线程在控制着进程的执行,一个进程中至少有一个线程。

Java VM启动的时候会有一个进程java.exe;

jvm启动不止一个线程,还有负责垃圾回收机制的线程

如何自定义一个线程:

         1,Java已经提供的对线程描述就是Thread类,创建线程的一种方法就是继承Thread类;该类定义了一个功能,用于存储线程要执行的代码,该存储功能就是run方法;

classDemo extends Thread{//1,定义类继承Thread

public voidrun(){//2,复写Thread类中的run方法,目的:将自定义的代码存储在run方法中,让线程运行;

                            执行语句;

                   }

}//3,在主函数中用 Demo类实例对象调用start方法,该方法的作用,启动线程、调用run方法;

如果在main方法中利用Demo的实例对象(创建线程)调用run方法,仅//仅是对象调用方法,而线程创建了,并没有运行;

为什么要覆盖run方法:Thread类中run方法是存储要执行代码,这些代码会根据实现的功能不同,存储指定的代码进去;

        2,创建线程的另一种方法是声明实现Runnable接口类,该类然后实现run方法然后可以分配该类的实例,在创建Thread时作为一个参数来传递并启动:

classPrimeRun implements Runnable{

publicvoid run(){

执行语句;

}

}

创建并启动一个线程:

PrimeRunp = new PrimeRun();

newThread(p).start();

步骤:1,定义类实现Runnable接口;

2,覆盖Runnable接口中的run方法:将线程中运行的代码存放在run方法中;

3,通过Thread类创建线程对象;

4,将Runnable接口的子类对象作为实参传递给Thread类的构造函数,

为什么要将Runnable接口的子类对象传给Thread的构造函数:

因为自定义的run方法所属的对象时Runnable接口的子类对象, 所以要让线程去执行指定对象的run方法,就必须明确该run方法所属对象;

 5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法;

实现方式(Runnable)和继承方式(Thread)有什么区别?

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

继承Thread类:线程代码存放Thread子类run方法中;

实现Runnable:线程代码存放在接口的子类run方法中;

使用多线程要小心安全问题,问题原因:

当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有执行完,另一个线程参与进来执行,导致共享数据的错误;

 解决方法:对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行;

Java对于多线程的安全问题提供了专业的解决方法:就是同步代码块;

synchronized(对象){//这个对象可以是任意类的对象,这个对象就叫做锁(监视器)

需要被同步的代码

}//持有锁的线程可以在同步块中执行,没有持有锁的线程即使获取了CPU的执行权,也进不去

同步前提:1,必须要有两个或者两个以上的线程;

2,必须是多个线程使用同一锁;

弊端:多个线程需要判断锁时,较为消耗资源,影响运行效率

如何找问题:

1,明确哪些代码是多线程运行代码;

2,明确共享数据;

3,明确多线程运行代码中哪些语句是操作共享数据;

同步函数:synchronied返回值类型 函数名(){}

函数需要被对象调用,那么函数都有一个所属对象应用,就是this,所以同步函数使用的锁就是this;

静态同步函数,使用的锁是该方法所在类的字节码文件对象,类名.class;

死锁:同步中嵌套同步,但锁不是同一个锁;              

发现运行结果每一次都不同,因为多个线程都获取CPU的执行权,CPU执行到谁,谁就运行;明确一点,在某一个时候,只能有一个程序在运行(多核除外)

CPU在做着快速的切换,以达到看上去是同时运行的效果;这就是多线程的一个特性,随机性,谁抢到谁执行,至于执行多长,CPU决定。    

线程状态:睡眠(sleep(time)),等待(wait()需要唤醒notify()),消亡(stop()),运行(start())

临时状态:阻塞状态,具备运行资格、等待CPU的执行权;

特例:写个延迟加载的单例设计模式示例:
/*

*懒汉式单例:特点,实例的延迟加载;

*懒汉式延迟加载的问题:当多个线程访问时会存在安全问题;

*安全问题解决:加同步的方式解决 ,可以使同步代
aaaa
码快,或使同步函数都行,但是降低程序效率,用双层判断可以解决效率问题;

*加同步使用的锁:该方法所在类的字节码文件对象

*/

class Single{

         privatestatic Single s = null;

         publicstatic Single getInstance(){

                   if(s== null)//双层判断

                            synchronized(Single.class){//加同步的方式解决安全问题//锁Single.class是:该方法所在类的字节码文件对象

                                     if(s==null)//双层判断,来解决效率问题

                                               s= new Single();//实例的延迟加载

                            }

                   }

                   returns;

         }

}       

练习1:创建两个线程和主线程交替运行;

线程都有自己默认的名称:Thread-编号,该编号从零开始;

static Thread currentThread();获取当前线程对象

getName():获取线程名称;

setName():设置线程名称(或者构造函数)

class Test extends Thread{

         publicvoid run(){

                   for(inti=0;i<60;i++){

                            System.out.println("testrun:"+i);

                   }

         }

}

class ThreadTest{

         publicstatic void main(String[] args){

                   Testt1 = new Test();

                   Testt2 = new Test();

                   t1.start();//使用start方法是输出结果是不确定

                   t2.start();

                   //t1.run();//使用run方法输出的结果是确定的

                   //t2.run();

                   for(inti=0;i<60;i++){

                            System.out.println("main:"+i);

                   }

         }

}

练习2:一个死锁程序

class MyLock{

         staticObject locka = new Object();

         staticObject lockb = new Object();

}

class Test implements Runnable{

         privateboolean flag;

         Test(booleanflag){

                   this.flag= flag;

         }

         publicvoid run(){

                   if(flag)

                   {

                            synchronized(MyLock.locka){

                                     System.out.println("iflocka");

                                     synchronized(MyLock.lockb){

                                               System.out.println("iflockb");

                                     }

                            }

                   }else

                   {

                            synchronized(MyLock.lockb){

                                     System.out.println("elselockb");

                                     synchronized(MyLock.locka){

                                               System.out.println("elselocka");

                                     }

                            }

                   }

         }

}

class DeadLockTest{

         publicstatic void main(String[] args){

                   newThread(new Test(true)).start();

                   newThread(new Test(false)).start();

         }

}

-------
android培训、java培训、期待与您交流! ----------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: