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

黑马程序员---java多线程学习总结

2014-03-27 12:25 435 查看
----------------------
ASP.Net+Unity开发,.Net培训、期待与您交流! ----------------------
 
java多线程学习总结:
 1.线程是程序的一条执行路径,多线程就是程序可以同时有多条执行路径.

 2.多线程的多条执行路径只是逻辑上的,在任意时刻,只能有一条执行路径得以执行,如果多条执行路径操作互斥的资源,如果不加控制,程序可能会出错

 3.对于操作互斥资源的线程,通常通过synchronized原语来创建同步代码块或同步函数,以此来线程对互斥资源的互斥访问

 4.synchronized原语通过给对象加锁的方式工作:

5.死锁产生的必要条件:

   1.互斥条件  :线程本身持有对方请求的锁,但请求对方持有的锁

   2.请求保持条件 :线程会一直请求未获取的对方的锁

   3.不可剥夺条件:线程不会主动释放自己的锁

 6.线程工作状态有运行状态,等待状态冻结状态就绪状态创建状态结束状态
 7.静态同步函数的锁是class对象,同步代码块的锁是this对象

 8.线程的两种创建方式:

    1.通过继承Thread类,并重写该类中的run()方法:

/**
*可以通过继承Thread类来创建线程,创建好的线程还要调用他的
*Start方法才能运行,调用Start方法后,线程不会立即运行,Start
*方法只是让线程处于就绪状态,使线程具备运行的条件,线程必须
*获得CPU才能真正的运行。一般的不推荐通过继承Thread类来创建线
*程,因为Java的单根继承,可能我们的类还要继承其他的类,这样,
*如果继承了Thread类就不能再继承其他类了
*/
class ThreadDemo extends Thread{
public void run{
//在这里定义自定义用户代码
}
}
new ThreadDemo().start();


   2.通过实现Runnable接口,并实现它的run()方法:

/**
*通过实现Runnable接口来创建线程,推荐使用这个方法,
*实现了Runnable接口的类必须通过Thread类才能创建线程
*即:把实现了Runnable接口的类当作Thread类构造函数的
*参数传给Thread类,然后通过Thread类的Start方法启动线程
*/
class ThreadDemo implements Runnable{
public void run(){
//用户自定义代码
}
new Thread(new ThreadDemo()).start();


 9.synchronized原语的用法:

 

/**
*synchronized关键字对锁没有要求,任何对象都可以作为锁
*唯一的要求是被当作锁的对象在不同的线程中是可见的,也就是
*说,在需要访问互斥或同步代码的线程中是可以访问到这个对象的,通常
*用作锁的对象一般是全局对象或类对象,这样,任何线程都可以访问
*到他们。synchronized关键字在对函数进行加锁时,锁的是函数所属
*的类的类对象。
*/
//用synchronized构建同步代码块:
Object obj=new Object();
synchronized(obj){
//用户自定义同步代码

}
//用synchronized构建静态同步函数:
public synchronized static void fun(){

}


 10.单例设计模式-懒汉式:

  

/**
*单例设计模式是一个类在内存中只有一个实例对象,通常是将
*这个类的构造方法私有化,然后提供一个获取类实例对象的方
*法,因为无法new出实例对象,只能通过类给出的方法获取实例
*对象,因此只需要保证类给出的方法只产生一个实例对象就行了,
*通常在类的内部定义一个静态的实例变量,然后通过类给出的方法
*返回这个实例变量就行了,当这个实例变量是在类中被初始化的时候
*饱汉式,当这个实例变量是在类给出的方法中被实例化时称之为饿汉式
*/
class singleObj{
private static singleObi Obj=null;//先声明一个类引用而不去实例化他
private singleObj(){}//构造方法私有化,这样就无法在类外面new出实例对象了
public synchronized static singleObj getInstance(){
if(Obj==null)
Obj=new singleObj();//第一次调用方法式实例化类对象,以后直接返回类对象
return Obj;
}
}


 

 11.改进的线程间通讯机制示例,基于java.util.concurrent.locks 

   

/**
*普通的通过synchronized关键字给需要互斥或同步访问的资源加锁
*的方式对锁的释放有着严格的要求,即后加锁的资源要先释放,先加锁
*的资源要后释放,这在需要多重锁的资源上,极易因锁释放的顺序不当
*造成死锁,Lock类本身可以检测死锁,而且对锁的释放顺序没有要求,
*对那些需要多重加锁或循环加锁的资源,使用Lock类将使编写代码的难度
*大大降低,而且,当预测到将有死锁发生时,通过强行释放锁,可以避免
*死锁的发生,使程序员不必因死锁问题而伤脑筋。
*/
class lockTicketDemo{
final Lock lock =new ReentrantLock();//创建锁的实例
final Condition noticket=lock.newCondition();//为每个需要互斥访问余票的方法创建Condition对象
final Condition ticketfull=lock.newCondition();
int ticket=1000;
public void saleTicket()throws Exception{
lock.lock();
try{
while(ticket<=0)
noticket.await();//当余票不足时,调用Condition的await方法是当前方法阻塞,等待其他方法更新余票数量后将其唤醒
System.out.println("还剩"+(ticket--)+"张票");//当前方法被唤醒,表示其他方法已经生产了一张余票
Thread.sleep(1000);
ticketfull.signsl();//售出一张票后,调用Condition的signsl()方法唤醒生产余票的方法,以保证有足够多的余票
}finally{
lock.unlock();
}

}
public void buyTicket()throws Exception{
lock.lock();
try{
while(ticket>1000)
ticketfull.await();//当余票数量过多时,阻塞自己,等待其他方法将余票销售一部分后再唤醒自己
System.out.println("现在还有"+(ticket++)+"张票");//当前方法被唤醒,表示其他方法已经销售了一张余票
Thread.sleep(1000);
noticket.signal();//生产一张余票后唤醒销售余票的方法,以保证余票不会堆积过多
}finally{
lock.unlock();}
}
}


 12.守护线程是由虚拟机托管的线程,当所有的非守护线程运行结束后,所有的守护线程都将由虚拟机结束运行,可以在创建线程的时候指明其是否为守护线程 
,设置线程为守护线程必须在线程启动前,如果一个线程

 是守护线程,那么这个线程创建的线程也是守护线程,设置线程为守护线程的方法:

  

4000
Thread t=new Thread(){public void run(){}};
t.setDaemon(true);//setDaemon方法可以将一个线程设置为守护线程,这个方法必须在线程启动前调用。
t.start();


 13.每个线程都有其优先级,优先级从低到高为1到10级,在进行线程调度时,高优先级的线程优先获得CPU执行权,设置线程优先级可以用Thread类的setPriority()函数:

  

Thread t=new Thread(){public void run(){}};
t.setPriority(10);//setPriority方法可以设置线程的优先级,这里设置的是静态优先级,线程在运行过程中优先级是不断变化的,动态优先级由操作系统设置。
t.start();


 14.线程结束的方法:1设置为守护线程,当前台线程结束后由jvm结束 2在进程中设置结束标记,3通过线程中断,并在中断处理函数中结束

 

----------------------
ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------

详细请查看:www.itheima.com
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: