java 线程 Thread 使用介绍,包含wait(),notifyAll() 等函数使用介绍

简介: (原创,转载请说明出处!谢谢--http://www.cnblogs.com/linguanh/)    此文目的为了帮助大家较全面、通俗地了解线程 Thread 相关基础知识!   目录:        --线程的创建:        --启动线程        --线程的调度        --Thread 类的简介        --线程的同步/异步        --wait() 和 notify(),notifyAll()方法       在讲线程之前,先说下进程。

(原创,转载请说明出处!谢谢--http://www.cnblogs.com/linguanh/)

 

 此文目的为了帮助大家较全面、通俗地了解线程 Thread 相关基础知识!

 

目录:

       --线程的创建:

       --启动线程

       --线程的调度

       --Thread 类的简介

       --线程的同步/异步

       --wait() 和 notify(),notifyAll()方法

     

在讲线程之前,先说下进程。

 

进程:是运行系统中,每个独立运行的程序。例如win7,我既用酷狗软件听歌,又玩 LOL 游戏,又上QQ,那么这就有3个进程。

线程:一个进程里面有很多线程,进程是由线程组成的,线程的结束不一定会导致进程结束,而一个进程的结束,则会连带它里面的所有线程被结束。

 

------------线程的创建:

创建->

        java 中有两种方式:

        1,一种是通过实现Runnable 接口

        2,另一种是继承线程类 Thread

实现Runnable接口的实例代码:

1 class threadT implements Runnable{
2     @Override
3     public void run() {
4         //在这编辑要执行的代码
5     }
6 }

上述代码,通过实现 Runnable 的接口,重写接口函数 run() 来实现新建一个线程。类比,点击事件的接口 OnClickListener

 

实现:

1 Thread thread_test = new Thread(new threadT);
2  //实例化代码一般放在主线程中,例如 main 中 或 onCreate()

 

继承线程类Thread 的实例代码:

1 class threadT1 extends Thread{
2         public void run(){
3          // edit your code
4         }
5  }

 

实现:

1 Thread thread_test = new ThreadT1();
thread_test.start();

 

上述两种方法的比较:

      本人建议使用第一种,即使用实现Runnable 接口的方法来新建线程。

      原因:

            1:避免java 的单一 继承带来的局限;

            2:和 onClickListener 点击事件一样,当你有多个线程时,使用Runnable 再在run内用一个 switch 就能分开使用;

 

--------------启动线程:

线程的启动一般都是通过方法执行 statrt() 进行的。

 

完整 main 函数测试代码:

 1 package com.LGH.ew;
 2 
 3 /**
 4  *  Created by Administrator on 2015/4/25.
 5  *  各线程,当主线程main 执行完了,它们还会继续执行,彼此不影响
 6  *  多线程卖票 显示 demo,by LinGuanHong
 7  */
 8 public class threadTest {
 9     public static void main(String[] args){
10         threadT t1 = new threadT1();//线程 1
11         Thread t2 = new Thread(new ThreadT());//线程 2
12        
13         t2.start();
14         t1.start();
15     }
16 }

 

------------线程的调度:

调度是什么意思呢?就是 cpu 执行每个线程的顺序,注意,不一定是按顺序的,这个和线程的优先级有关!

线程的调用是统一由JVM根据时间片来调度的,其执行顺序随机。大致执行流程如下:

 

 

由上述可以看出, jvm 在执行多线程 程序的时候,在某一个时间段,其实也是只能运行一个线程,

但是它用划分时间片段的机制来转换调用各个线程,这个时间片段很短!

 

-----------Thread 类的简介

 

java.lang.Thread 类:

    常用的方法有:

    ---public void start(); 启动该线程,其中调用了这个方法不一定就立即进行,还要看是否被调度到;

    ---public static Thread currentThread(); 静态方法,这个方法很重要,用来返回当前正在执行的线程对象引用;

    ---public final booleann isAlive();测试线程是否还活着;

    ---public Thread.State getState();返回该线程当前的状态,

                 分别有:

                          NEW 实例化了,但尚未启动的线程是这种状态,新建 态;

                          RUNNABLE 正在被执行的状态;

                          BLOCKED 受阻塞并等待某个监视器锁的线程态;

                          WAITING 无限期地等待另外一个线程来执行特地操作,等待 态;

                          TIMED_WAITING 等待另一个线程来执行取决于指定等待时间的操作,超时等待 态

                          TERMINATED 已退出的线程的状态,终止 态。

     ---public final String getName();返回线程名称,一般和setName(),连用;

     ---public final void setDaemon(boolean on);将该线程标记为守护线程;

     ---public static void sleep(long millis);在指定的毫秒内,让该线程暂停;

     ---public final void setPriority(int level);设置线程的优先级,可以是 1,5,10,分别是 低、普通、最高,默认是 5 ;

     ---public static void yield();线程让步,它会暂停该线程,把执行的机会让给相同或优先级更高的线程;

     ---public void final join();把某线程加入到某线程中去,被加者变为子线程;

     ---public void interrupt(); 中断线程.

 

------------线程的生命周期

 

其生命周期可以总结为上面的 6个 状态,图解如下:

 

-------------线程的同步/异步

下面通过demo 代码说明,内涵 synchronized 保护机制

 

  1 package com.LGH.ew;
  2 
  3 /**
  4  *  Created by Administrator on 2015/4/25.
  5  *  各线程,当主线程main 执行完了,它们还会继续执行,彼此不影响
  6  *  多线程卖票 显示 demo,by LinGuanHong
  7  */
  8 public class threadTest { //卖火车票例子
  9     public static void main(String[] args){
 10         threadT T = new threadT();
 11         Thread t1 = new Thread(T);//线程 1
 12         t1.setName("1");// 设置 线程名字
 13         //t1.getState(); 这里有具体的线程对象,所以可以直接使用其类方法;
 14         t1.start();
 15         Thread t2 = new Thread(T);//线程 2
 16         t2.setName("2");
 17         t2.start();
 18         Thread t3 = new Thread(T);//线程 3
 19         t3.setName("3");
 20         t3.start();
 21         Thread t4 = new Thread(T);//线程 4
 22         t4.setName("4");
 23         t4.start();
 24         Thread t5 = new Thread(T);//线程 5
 25         t5.setName("5");
 26         t5.start();
 27     }
 28 }
 29 class threadT implements Runnable{ //实例化接口 
 30     private int tickets = 0;
 31     @Override
 32     public void run() {
 33         boolean control = true;
 34         while(control){
 35             control = sell();//调用sell 方法,大家可以通过改变这个函数的调用,来看异步、同步的效果
 36         }
 37     }
 38 
 39     public boolean sell(){//异步线程机制,会被打断,所谓打断,就是会出现 线程1 卖了第2张票时,线程3也卖了第2 张
 40         boolean control = true ;
 41         if(tickets<100){
 42             tickets ++;
 43             //在函数内,如果没有具体的线程对象,就要使用静态方法 currentThread() 返回当前正在执行的线程对象的引用,在使用类方法
 44             System.out.println(Thread.currentThread().getName()+":"+tickets);//同上
 45             Thread.State state = Thread.currentThread().getState();//同上
 46             System.out.println("State:"+state.toString());//输出当前的状态,正常是 runnable
 47         }else{
 48             control = false;
 49         }
 50         try{
 51             Thread.sleep(1);
 52         }catch (Exception e){
 53             e.printStackTrace();
 54         }
 55         return control;
 56     }
 57 
 58     //关键字 - synchronized 保护 当前 函数在执行时不被其他线程打断,同步线程机制
 59     //整体同步,效率低
 60     public synchronized boolean sell1(){ 
 61         boolean control = true ;
 62         if(tickets<100){
 63             tickets ++;
 64             //在函数内,如果没有具体的线程对象,就要使用静态方法 currentThread() 返回当前正在执行的线程对象的引用,在使用类方法
 65             System.out.println(Thread.currentThread().getName()+":"+tickets);//同上
 66             Thread.State state = Thread.currentThread().getState();//同上
 67            // System.out.println("State:"+state.toString());
 68         }else{
 69             control = false;
 70         }
 71         try{
 72             Thread.sleep(1);
 73         }catch (Exception e){
 74             e.printStackTrace();
 75         }
 76         return control;
 77     }
 78     //关键字 - synchronized 实质是一个对象锁
 79 
 80     public boolean sell2(){ // 条件 关键字 - synchronized 保护 当前 函数在执行时不被其他线程打断,同步线程机制
 81         boolean control = true ;
 82         synchronized(this) { //仅仅同步会操作到的共同部分变量,tickets,这样避免同步整体,提高效率
 83             if (tickets < 100) {
 84                 tickets++;
 85                 //在函数内,如果没有具体的线程对象,就要使用静态方法 currentThread() 返回当前正在执行的线程对象的引用,在使用类方法
 86                 System.out.println(Thread.currentThread().getName() + ":" + tickets);//同上
 87                 Thread.State state = Thread.currentThread().getState();//同上
 88                 // System.out.println("State:"+state.toString());
 89             } else {
 90                 control = false;
 91             }
 92         }
 93         try{
 94             Thread.sleep(1);
 95         }catch (Exception e){
 96             e.printStackTrace();
 97         }
 98         return control;
 99     }
100 }

 

-------------wait() 和 notify(),notifyAll()方法

他们是同步机制中的重要部分,必须和 synchronized 关键字结合使用,即在 synchronized 代码块中使用!

否在 抛出 Illegal..... 非法异常。

wait() 被调用,当前线程将会被中断运行,并且放弃该对象的锁;

执行了 notify() 后,会唤醒此对象等待池中的某个线程,使之成为可运行的线程;

notifyAll()则唤醒所有;

 

下面用一个具体的demo 说明:

前言-------------

     生产者和消费者的问题,生产者将产品交给店员,而消费者从店员处取走产品,店员一次只能持有固定的产品,如果生产者生产过多了的产品,店员会叫生产者等一下,如果店中有空位放产品了再通知生产者继续生产;

     如果店中供不应求,店员会叫消费者等一会,等生产者生产了再叫消费者来拿。

问题:

      生产者生产过快,消费者会漏掉一些,没取到;

      消费者比生产者快,消费者会拿到相同的;

 

 1 package com.LGH.ew.view;
 2 
 3 /**
 4  * Created by Administrator on 2015/4/25.
 5  */
 6 public class Product { //生产者、消费者问题
 7     public static void main(String[] args){
 8         clerk c = new clerk();
 9         Thread productT = new Thread(new Producer(c));//生产者线程
10         Thread consumerT = new Thread(new Consumer(c));//消费者线程
11         productT.start();
12         consumerT.start();
13     }
14 }
15 class clerk{ //店员
16     private int product = 0; //默认 0 个产品
17     public synchronized void addproduct(){ //生产出的产品,交给店员
18         if(this.product>=20){
19             try{
20                 wait(); //产品过多,稍后再生产
21             }catch (Exception e){
22                 e.printStackTrace();
23             }
24         }else{
25             product++;
26             System.out.println("生产者生产第"+product+"个产品。");
27             notifyAll(); //通知等待区的消费者可取产品
28         }
29     }
30     public synchronized void getproduct(){ //消费者从店员处取产品
31         if(this.product<=0){
32             try{
33                 wait(); //缺货,稍后再取
34             }catch (Exception e){
35                 e.printStackTrace();
36             }
37         }else{
38             System.out.println("消费者取走了第:" + product + "产品。");
39             product--;
40             notifyAll(); //通知等待取得生产者可以继续生产
41         }
42     }
43 }
44 
45 class Producer implements Runnable{ //生产者线程
46 
47     private clerk c;
48     public Producer(clerk c){
49         this.c = c;
50     }
51     @Override
52     public void run() {
53         System.out.println("生产者开始生产产品。");
54         while(true){
55             try{
56                 Thread.sleep((int)(Math.random()*10)*100);
57             }catch(Exception e){
58                 e.printStackTrace();
59             }
60             c.addproduct(); //生产
61         }
62     }
63 }
64 
65 class Consumer implements Runnable{ //消费者线程
66 
67     private clerk c ;
68 
69     public Consumer(clerk c){
70         this.c = c;
71     }
72     @Override
73     public void run() {
74         System.out.println("消费者开始取走产品。");
75         while(true){
76             try{
77                 Thread.sleep((int)(Math.random()*10)*100);
78             }catch(Exception e){
79                 e.printStackTrace();
80             }
81             c.getproduct(); //取产品
82         }
83     }
84 }

 

全文终,各位如果觉得还可以的话,请帮忙点个赞,让更多人能看到。谢谢

 

如果您认为这篇文章还不错或者有所收获,您可以通过扫描一下下面的支付宝二维码 打赏我一杯咖啡【物质支持】,也可以点击右下角的【推荐】按钮【精神支持】,因为这两种支持都是我继续写作,分享的最大动力


img_12e3f54d4d0f70f0eb14f20548e3d781.png
目录
相关文章
|
14天前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
5天前
|
缓存 Java 开发者
Java多线程编程的陷阱与最佳实践####
本文深入探讨了Java多线程编程中常见的陷阱,如竞态条件、死锁和内存一致性错误,并提供了实用的避免策略。通过分析典型错误案例,本文旨在帮助开发者更好地理解和掌握多线程环境下的编程技巧,从而提升并发程序的稳定性和性能。 ####
|
4天前
|
安全 Java 开发者
Java中的多线程编程:从基础到实践
本文深入探讨了Java多线程编程的核心概念和实践技巧,旨在帮助读者理解多线程的工作原理,掌握线程的创建、管理和同步机制。通过具体示例和最佳实践,本文展示了如何在Java应用中有效地利用多线程技术,提高程序性能和响应速度。
28 1
|
12天前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
|
13天前
|
Java 开发者
Java多线程编程的艺术与实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的技术文档,本文以实战为导向,通过生动的实例和详尽的代码解析,引领读者领略多线程编程的魅力,掌握其在提升应用性能、优化资源利用方面的关键作用。无论你是Java初学者还是有一定经验的开发者,本文都将为你打开多线程编程的新视角。 ####
|
12天前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
18天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
44 9
|
15天前
|
安全 Java 开发者
Java多线程编程中的常见问题与解决方案
本文深入探讨了Java多线程编程中常见的问题,包括线程安全问题、死锁、竞态条件等,并提供了相应的解决策略。文章首先介绍了多线程的基础知识,随后详细分析了每个问题的产生原因和典型场景,最后提出了实用的解决方案,旨在帮助开发者提高多线程程序的稳定性和性能。
|
17天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
2月前
|
存储 消息中间件 资源调度
C++ 多线程之初识多线程
这篇文章介绍了C++多线程的基本概念,包括进程和线程的定义、并发的实现方式,以及如何在C++中创建和管理线程,包括使用`std::thread`库、线程的join和detach方法,并通过示例代码展示了如何创建和使用多线程。
48 1
C++ 多线程之初识多线程