Java多线程

线程的概念:

程序 进程与线程的区别:

  程序是一个静态的代码或者说静态的存在.而进程是程序的一次运行过程. 

  多个进程的内部数据和状态都是完全独立的,而多线程是共享一块内存空间和一组系统资源,有可能互相影响.

  线程本身的数据通常只有寄存器数据,以及一个程序执行时使用的堆栈,所以线程的切换比进程切换的负担要小。



线程的实现方法:

继承Thread类

      Thread 类是一个具体的类,即不是抽象类,该类封装了线程的行为。要创建一个线程,程序员必须创建一个

 Thread 类导出的新类。程序员必须覆盖 Thread 的 run() 函数来完成有用的工作。用户并不直接调用此函数;而是必

须调用 Thread 的 start() 函数,该函数再调用 run()。

实现Runnable接口

     有时要作为线程运行的类可能已经是某个类层次的一部分,所以就不能再按这种机制创建线程。对于这种情况,就

要 runnable 接口.实现Runnable接口, 提供run()方法的具体实现, 最后生成该类的实例, 并作为参数传入Thread类的构造

方法来创建线程。可以从其他类继承,简化类层次,并将Thread类与任务处理类分开。

实例代码分别如下:

  1. public class myThread01 extends Thread {  
  2.     private int i = 0;  
  3.   
  4.     public myThread02(String str) {  
  5.         super(str);  
  6.     }  
  7.   
  8.     public void run() {  
  9.   
  10.         while (i < 100) {  
  11.             System.out.println(getName() + " 完成了" + i + "% 的工作");  
  12.             i++;  
  13.             try {  
  14.                 Thread.sleep(1000);  
  15.             } catch (InterruptedException e) {  
  16.                 e.printStackTrace();  
  17.             }  
  18.         }  
  19.     }  
  20.   
  21.     public static void main(String[] args) {  
  22.         new myThread01("worker01").start();  
  23.         new myThread01("worker02").start();  
  24.         new myThread01("worker03").start();  
  25.         new myThread01("worker04").start();  
  26.     }  
  27.   
  28. }  

  1. public class myThread02 implements Runnable {  
  2.     private int i = 0;  
  3.   
  4.     public void run() {  
  5.   
  6.         while (i < 100) {  
  7.             System.out.println(Thread.currentThread().getName() + " 完成了" + i  
  8.                     + "% 的工作");  
  9.             i++;  
  10.             try {  
  11.                 Thread.sleep(1000);  
  12.             } catch (InterruptedException e) {  
  13.                 e.printStackTrace();  
  14.             }  
  15.         }  
  16.     }  
  17.   
  18.     public static void main(String[] args) {  
  19.         myThread02 mt = new myThread02();  
  20.         for (int i = 0; i < 4; i++) {  
  21.             new Thread(mt).start();  
  22.         }  
  23.     }  
  24.   
  25. }  

线程的生命周期:

新状态:线程已被创建但尚未执行(start() 尚未被调用)。

可执行状态:线程可以执行,虽然不一定正在执行。CPU 时间随时可能被分配给该线程,从而使得它执行。

死亡状态:正常情况下 run() 返回使得线程死亡。调用 stop()或 destroy() 亦有同样效果,但是不被推荐,前者会产生异

常,后者是强制终止,不会释放锁。

阻塞状态:线程没有被分配 CPU 时间,无法执行。



线程退出最好自己实现,在运行状态中一直检验一个状态,如果这个状态为真,就一直运行,如果外界更改了这个状态变量,那么线程就停止运行。 

1.sleep()方法

在指定时间内让当前正在执行的线程暂停执行,但不会释放“锁标志”。不推荐使用。sleep()使当前线程进入阻塞状态,

在指定时间内不会执行。

2.wait()方法

在其他线程调用对象的notify或notifyAll方法前,导致当前线程等待。线程会释放掉它所占有的“锁标志”,从而使别的线

程有机会抢占该锁。一直等到有人通知我,我才会运行后面的代码。 

当前线程必须拥有当前对象锁。如果当前线程不是此锁的拥有者,会抛出IllegalMonitorStateException异常。

唤醒当前对象锁的等待线程使用notify或notifyAll方法,也必须拥有相同的对象锁,否则也会抛出

IllegalMonitorStateException异常。(notify()方法表示,当前的线程已经放弃对资源的占有, 通知等待的线程来获得对资源的占有权,但是只有一个线程能够从wait状态中恢复, 然后继续运行wait()后面的语句; notifyAll()方法表示,当前的线程已经放弃对资源的占有, 通知所有的等待线程从wait()方法后的语句开始运行。 )

wait() 和notify()必须在synchronized函数或synchronized block中进行调用。如果在non-synchronized函数或non-

synchronized block中进行调用,虽然能编译通过,但在运行时会发生 IllegalMonitorStateException的异常。

3.yield方法

暂停当前正在执行的线程对象。yield()只是使当前线程重新回到可执行状态,所以执行yield()的线程有可能

在进入到可执行状态后马上又被执行。yield()只能使同优先级或更高优先级的线程有执行的机会。

4.join方法

等待该线程终止。等待调用join方法的线程结束,再继续执行。如:t.join();//主要用于等待t线程运行结束,若无此句,

main则会执行完毕,导致结果不可预测。


线程的同步:

一个Java程序的多线程之间可以共享数据。当线程以异步方式访问共享数据时,有时候是不安全的或者不和逻辑的。

比如,同一时刻一个线程在读取数据,另外一个线程在处理数据,当处理数据的线程没有等到读取数据的线程读取完毕

就去处理数据,必然得到错误的处理结果。 

Java 编程语言提供了一种简单的机制来防止发生这种覆盖。每个对象在运行时都有一个关联的锁。这个锁可通过为方

法添加关键字 synchronized 来获得。


同步有两种方式:

同步块:对易发生冲突的语句块加锁 

同步方法:对易发生冲突的方法块加锁

分别实例如下:

  1. class SellThread implements Runnable {  
  2.         int tickets = 100;  
  3.         Object obj = new Object();  
  4.   
  5.         public void run() {  
  6.             while (true) {  
  7.                 synchronized (obj) {  
  8.                     if (tickets > 0) {  
  9.                         System.out.println(Thread.currentThread().getName()  
  10.                                 + " sell tickets:" + tickets);  
  11.                         tickets--;  
  12.                     }  
  13.                 }  
  14.             }  
  15.         }  
  16.     }  

  1. class SellThread implements Runnable{  
  2.      int tickets=100;  
  3.      public void run(){    
  4.          sell();   
  5.      }  
  6.      public synchronized void sell(){  
  7.          while(true){    
  8.      if(tickets>0){    
  9.               System.out.println(Thread.currentThread().getName()+  
  10.                         " sell tickets:"+tickets    
  11.                   tickets--;  
  12.              }  
  13.          }        
  14.      }    

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值