java中的多线程(二)

线程的休眠:

  
  
  
  
  1. /** 
  2.  * @author Rollen-Holt 线程的休眠 
  3.  * */ 
  4. class hello implements Runnable { 
  5.     public void run() { 
  6.         for (int i = 0; i < 3; i++) { 
  7.             try { 
  8.                 Thread.sleep(2000); 
  9.             } catch (Exception e) { 
  10.                 e.printStackTrace(); 
  11.             } 
  12.             System.out.println(Thread.currentThread().getName() + i); 
  13.         } 
  14.     } 
  15.   
  16.     public static void main(String[] args) { 
  17.         hello he = new hello(); 
  18.         Thread demo = new Thread(he, "线程"); 
  19.         demo.start(); 
  20.     } 

【运行结果】:(结果每隔2s输出一个)

线程0

线程1

线程2

 

线程的中断:

  
  
  
  
  1. /** 
  2.  * @author Rollen-Holt 线程的中断 
  3.  * */ 
  4. class hello implements Runnable { 
  5.     public void run() { 
  6.         System.out.println("执行run方法"); 
  7.         try { 
  8.             Thread.sleep(10000); 
  9.             System.out.println("线程完成休眠"); 
  10.         } catch (Exception e) { 
  11.             System.out.println("休眠被打断"); 
  12.             return;  //返回到程序的调用处 
  13.         } 
  14.         System.out.println("线程正常终止"); 
  15.     } 
  16.   
  17.     public static void main(String[] args) { 
  18.         hello he = new hello(); 
  19.         Thread demo = new Thread(he, "线程"); 
  20.         demo.start(); 
  21.         try
  22.             Thread.sleep(2000); 
  23.         }catch (Exception e) { 
  24.             e.printStackTrace(); 
  25.         } 
  26.         demo.interrupt(); //2s后中断线程 
  27.     } 

【运行结果】:

执行run方法

休眠被打断

 

java程序中,只要前台有一个线程在运行,整个java程序进程不会小时,所以此时可以设置一个后台线程,这样即使java进程小时了,此后台线程依然能够继续运行。

  
  
  
  
  1. /** 
  2.  * @author Rollen-Holt 后台线程 
  3.  * */ 
  4. class hello implements Runnable { 
  5.     public void run() { 
  6.         while (true) { 
  7.             System.out.println(Thread.currentThread().getName() + "在运行"); 
  8.         } 
  9.     } 
  10.   
  11.     public static void main(String[] args) { 
  12.         hello he = new hello(); 
  13.         Thread demo = new Thread(he, "线程"); 
  14.         demo.setDaemon(true); 
  15.         demo.start(); 
  16.     } 

虽然有一个死循环,但是程序还是可以执行完的。因为在死循环中的线程操作已经设置为后台运行了。

线程的优先级:

  
  
  
  
  1. /** 
  2.  * @author Rollen-Holt 线程的优先级 
  3.  * */ 
  4. class hello implements Runnable { 
  5.     public void run() { 
  6.         for(int i=0;i<5;++i){ 
  7.             System.out.println(Thread.currentThread().getName()+"运行"+i); 
  8.         } 
  9.     } 
  10.   
  11.     public static void main(String[] args) { 
  12.         Thread h1=new Thread(new hello(),"A"); 
  13.         Thread h2=new Thread(new hello(),"B"); 
  14.         Thread h3=new Thread(new hello(),"C"); 
  15.         h1.setPriority(8); 
  16.         h2.setPriority(2); 
  17.         h3.setPriority(6); 
  18.         h1.start(); 
  19.         h2.start(); 
  20.         h3.start(); 
  21.           
  22.     } 

【运行结果】:

A运行0

A运行1

A运行2

A运行3

A运行4

B运行0

C运行0

C运行1

C运行2

C运行3

C运行4

B运行1

B运行2

B运行3

B运行4

。但是请读者不要误以为优先级越高就先执行。谁先执行还是取决于谁先去的CPU的资源、

 

另外,主线程的优先级是5.

线程的礼让。

在线程操作中,也可以使用yield()方法,将一个线程的操作暂时交给其他线程执行。

  
  
  
  
  1. /** 
  2.  * @author Rollen-Holt 线程的优先级 
  3.  * */ 
  4. class hello implements Runnable { 
  5.     public void run() { 
  6.         for(int i=0;i<5;++i){ 
  7.             System.out.println(Thread.currentThread().getName()+"运行"+i); 
  8.             if(i==3){ 
  9.                 System.out.println("线程的礼让"); 
  10.                 Thread.currentThread().yield(); 
  11.             } 
  12.         } 
  13.     } 
  14.   
  15.     public static void main(String[] args) { 
  16.         Thread h1=new Thread(new hello(),"A"); 
  17.         Thread h2=new Thread(new hello(),"B"); 
  18.         h1.start(); 
  19.         h2.start(); 
  20.           
  21.     } 

A运行0

A运行1

A运行2

A运行3

线程的礼让

A运行4

B运行0

B运行1

B运行2

B运行3

线程的礼让

B运行4

 

 同步和死锁:

【问题引出】:比如说对于买票系统,有下面的代码:

  
  
  
  
  1. /** 
  2.  * @author Rollen-Holt 
  3.  * */ 
  4. class hello implements Runnable { 
  5.     public void run() { 
  6.         for(int i=0;i<10;++i){ 
  7.             if(count>0){ 
  8.                 try
  9.                     Thread.sleep(1000); 
  10.                 }catch(InterruptedException e){ 
  11.                     e.printStackTrace(); 
  12.                 } 
  13.                 System.out.println(count--); 
  14.             } 
  15.         } 
  16.     } 
  17.   
  18.     public static void main(String[] args) { 
  19.         hello he=new hello(); 
  20.         Thread h1=new Thread(he); 
  21.         Thread h2=new Thread(he); 
  22.         Thread h3=new Thread(he); 
  23.         h1.start(); 
  24.         h2.start(); 
  25.         h3.start(); 
  26.     } 
  27.     private int count=5

【运行结果】:

5

4

3

2

1

0

-1

这里出现了-1,显然这个是错的。,应该票数不能为负值。

如果想解决这种问题,就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行,

其他的线程必须等到这个线程结束之后才能继续执行。

【使用线程同步解决问题】

采用同步的话,可以使用同步代码块和同步方法两种来完成。

 

【同步代码块】:

语法格式:

synchronized(同步对象){

 //需要同步的代码

}

但是一般都把当前对象this作为同步对象。

比如对于上面的买票的问题,如下:

  
  
  
  
  1. /** 
  2.  * @author Rollen-Holt 
  3.  * */ 
  4. class hello implements Runnable { 
  5.     public void run() { 
  6.         for(int i=0;i<10;++i){ 
  7.             synchronized (this) { 
  8.                 if(count>0){ 
  9.                     try
  10.                         Thread.sleep(1000); 
  11.                     }catch(InterruptedException e){ 
  12.                         e.printStackTrace(); 
  13.                     } 
  14.                     System.out.println(count--); 
  15.                 } 
  16.             } 
  17.         } 
  18.     } 
  19.   
  20.     public static void main(String[] args) { 
  21.         hello he=new hello(); 
  22.         Thread h1=new Thread(he); 
  23.         Thread h2=new Thread(he); 
  24.         Thread h3=new Thread(he); 
  25.         h1.start(); 
  26.         h2.start(); 
  27.         h3.start(); 
  28.     } 
  29.     private int count=5

【运行结果】:(每一秒输出一个结果)

5

4

3

2

1

【同步方法】

也可以采用同步方法。

语法格式为synchronized 方法返回类型方法名(参数列表){

    // 其他代码

}

现在,我们采用同步方法解决上面的问题。

  
  
  
  
  1. /** 
  2.  * @author Rollen-Holt 
  3.  * */ 
  4. class hello implements Runnable { 
  5.     public void run() { 
  6.         for (int i = 0; i < 10; ++i) { 
  7.             sale(); 
  8.         } 
  9.     } 
  10.   
  11.     public synchronized void sale() { 
  12.         if (count > 0) { 
  13.             try { 
  14.                 Thread.sleep(1000); 
  15.             } catch (InterruptedException e) { 
  16.                 e.printStackTrace(); 
  17.             } 
  18.             System.out.println(count--); 
  19.         } 
  20.     } 
  21.   
  22.     public static void main(String[] args) { 
  23.         hello he = new hello(); 
  24.         Thread h1 = new Thread(he); 
  25.         Thread h2 = new Thread(he); 
  26.         Thread h3 = new Thread(he); 
  27.         h1.start(); 
  28.         h2.start(); 
  29.         h3.start(); 
  30.     } 
  31.   
  32.     private int count = 5

【运行结果】(每秒输出一个)

5

4

3

2

1

提醒一下,当多个线程共享一个资源的时候需要进行同步,但是过多的同步可能导致死锁。

此处列举经典的生产者和消费者问题。

 

你可能感兴趣的:(java,多线程)