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

黑马程序员_多线程

2011-09-30 13:06 197 查看
----------------------
android培训、java培训、期待与您交流! ----------------------
线程概念:

   一个进程中又可以包含一个或多个线程,一个线程就是一个程序内部的一条执行线索。在单线程中,程序代码按调用顺序依次往下执行,在这种情况下,当主函数调用了子函数,主函数必须等待函数返回后才能往下执行,不能实现两段程序代码同时交替运行的效果,如果要一程序代码段同时交替运行,就需要产生多个线程,并指定每个线程上所要运行的程序代码,这就是多线程。

多线程:main方法在调用run()之后会产生一个新的线程,而后将run()交给这个新的线程去运行,main方法继续执行后面的程序代码。

 

如果某个线程在调用start()方法之前调用了setDaemon(true)方法,这个线程就变成了后台线程。对于java来说,只要还有一个前台线程在运行,这个进程就不会结束,如果一个进程中只有后台线程运行,这个进程就会结束

 

join()方法  Test.join()即把Test所对应的线程合并到调用Test.join()语句的线程中,可以指定合并的时间

 

创建线程的方法有两种:

(1) 直接继承Thread类

(2)通过实现Runnable接口   通过new Thread( 传递进来的Runnable类型的对象 )  创建一个线程当线程start()的时候就不再调用Thread中的run(),而是调用Runnable对象中的run()

 

两种方式的区别:

1 通过直接继承Thread类

class  ThreadDemo1

{

         public static void main(String[] args)

         {

                   new TestThread().start();

                   new TestThread().start();

                   new TestThread().start();

                   new TestThread().start();

         }

}

 

class TestThread extends Thread

{

         int tickets = 100;

         public void run()

         {

                   while(true)

                   {

                            if(tickets > 0)

                            System.out.println(Thread.currentThread().getName() +"is saling ticket " + tickets--);

                   }

         }

}

以上 因为是new了四个TestThread对象,每个对象都有自己的100张票所以造成了四个窗口都卖了1号票这种现象发生

解决方法:只能是产生一个TestThread对象,然后让四个线程都执行它中的代码

2 通过实现Runnable接口

class  ThreadDemo1

{

         public static void main(String[] args)

         {

                   TestThread tt = new TestThread();

                   new Thread(tt).start();

                   new Thread(tt).start();

                   new Thread(tt).start();

                   new Thread(tt).start();

         }

}

 

class TestThread implements Runnable //extends Thread

{

         int tickets = 100;

         public void run()

         {

                   while(true)

                   {

                            if(tickets > 0)

                            System.out.println(Thread.currentThread().getName() +"is saling ticket " + tickets--);

                   }

         }

}

实现Runnable接口创建线程的方法适合多个相同程序代码的线程去处理同一资源的情况,还能避免java单继承的局限性

 

多线程的应用:网络聊天程序的收发, 表记录的复制中途取消, www服务器为每一个来访者都建立专线服务等

 

同步问题:

Sleep()方法   在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)

Synchronized   (必须是一个对象(监视器) 这个对象可以是任意类型的,任意一个对象都有一个标志位又叫锁旗标,有0和 1两种状态,当执行到synchronized对象时线程会检查对象标志位是1还是0,如果是1则继续向下执行同时将标志位变为0;如果为0,则线程会发生阻塞一直等到标志位为1才会继续向下执行)  保证同一时刻内只能有一个线程在运行

 

实现线程同步只需在方法前加synchronized关键字

如果多个线程要同步,它们使用的监视器必须是同一个对象

 

实现同步的两种方法:使用同步代码块;使用同步函数

当我们在多个方法前面加上synchronized关键字,当一个线程进入了某个synchronized关键字方法中时,其它的线程就不能够进入其它的任何使用synchronized关键字的方法中进行执行,也就是说当一个线程进入了某个synchronized关键字方法中时,它就得到并锁定了这个监视器

例子程序:

class  ThreadDemo1

{

         public static void main(String[] args)

         {

                   TestThread tt = new TestThread();

                   new Thread(tt).start();

                   new Thread(tt).start();

                   new Thread(tt).start();

                   new Thread(tt).start();

         }

}

 

class TestThread implements Runnable //extends Thread

{

         int tickets = 100;

         public void run()

         {

                 

                   while(true)

                   {

                            sale();

                   }

         }

 

         public synchronized void sale()

         {

                   if(tickets > 0)

                                     {

                                               try{Thread.sleep(10);}catch(Exception e){}

                                               System.out.println(Thread.currentThread().getName() +"is saling ticket " + tickets--);

 

                                     }

         }

}

执行的同步函数,则使用的监视器是this

执行的同步代码块,则使用的监视器是String对象

如果我们想让一个方法和某个代码块之间实现同步,则代码块中检查的监视器对象也必须使用this

 

线程启动的内部机制:一个线程调用start()方法,并不是说让这个线程马上开始执行,只是说这个线程处于启动状态了,CPU并不一定会马上来这个线程上执行  如果想让CPU马上过来执行,可以用sleep()(加tr
4000
y catch)

 

 

死锁的问题:等不到监视器,导致程序停滞不前

 

线程间的通信用到的几个方法:

notify();  唤醒同一对象监视器中调用wait()的第一个线程,即是为了唤醒被wait()阻塞了的线程继续向下执行

wait() 记得try catch  ,告诉当前线程放弃监视器并进入睡眠状态直到其他线程进入同一监视器并调用notify()为止

以上 必须使用同一个同步监视器,即线程得到锁旗标的对象

notifyAll() 唤醒同一对象监视器中调用wait()的所有线程,具有最高优先级的线程首先被唤醒并执行

 

线程通信例子程序:

class Producer implements Runnable

{

         HuanChong q;

         public Producer(HuanChong q)

         {

                   this.q = q;

         }

         public void run()

         {

                   int i = 0;

                   while(true)

                   {

                            if(i == 0)

                                     q.put("zhangsan","male");

                            else

                                     q.put("lisi","female");

                            i = (i+1)%2;   //i一直在0和1之间变化

                   }

         }

}

class Consumer implements Runnable

{

         HuanChong q;

         public Consumer(HuanChong q)

         {

                   this.q = q;

         }

         public void run()

         {

                   while(true)

                   {

                            q.get();

                   }

         }

}

 

class HuanChong

{

         private String name = "unknown";

         private String sex = "unknown";

         private boolean bFull = false; //判断缓冲区是否为空的变量

 

         public synchronized void put(String name,String sex)

         {

                   if(bFull)

                            try{wait();}catch(Exception e){}

                   this.name = name;

                   try{Thread.sleep(1);}catch(Exception e){}

                   this.sex = sex;

                   bFull = true;

                   notify();

         }

         public synchronized void get()

         {

                   if(!bFull)

                            try{wait();}catch(Exception e){}

                   System.out.println(name);

                   System.out.println(" : "+sex);

                   bFull = false;

                   notify();

         }

}

 

public class ThreadCommunation

{

         public static void main(String[] args)

         {

                   HuanChong q = new HuanChong();

                   new Thread(new Producer(q)).start();

                   new Thread(new Consumer(q)).start();

 

         }

}

 

run()方法结束了,程序就结束了

 ----------------------
android培训、java培训、期待与您交流! ---------------------- 详细请查看:http://edu.csdn.net/heima
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息