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

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

目录:

--线程的创建:

--启动线程

--线程的调度

--Thread 类的简介

--线程的同步/异步

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

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

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

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

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

创建->

java 中有两种方式:

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

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

实现Runnable接口的实例代码:

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

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

实现:

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

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

 class threadT1 extends Thread{
public void run(){
// edit your code
}
}

实现:

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

上述两种方法的比较:

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

原因:

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

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

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

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

完整 main 函数测试代码:

 package com.LGH.ew;

 /**
* Created by Administrator on 2015/4/25.
* 各线程,当主线程main 执行完了,它们还会继续执行,彼此不影响
* 多线程卖票 显示 demo,by LinGuanHong
*/
public class threadTest {
public static void main(String[] args){
threadT t1 = new threadT1();//线程 1
Thread t2 = new Thread(new ThreadT());//线程 2 t2.start();
t1.start();
}
}

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

调度是什么意思呢?就是 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 保护机制:

 package com.LGH.ew;

 /**
* Created by Administrator on 2015/4/25.
* 各线程,当主线程main 执行完了,它们还会继续执行,彼此不影响
* 多线程卖票 显示 demo,by LinGuanHong
*/
public class threadTest { //卖火车票例子
public static void main(String[] args){
threadT T = new threadT();
Thread t1 = new Thread(T);//线程 1
t1.setName("1");// 设置 线程名字
//t1.getState(); 这里有具体的线程对象,所以可以直接使用其类方法;
t1.start();
Thread t2 = new Thread(T);//线程 2
t2.setName("2");
t2.start();
Thread t3 = new Thread(T);//线程 3
t3.setName("3");
t3.start();
Thread t4 = new Thread(T);//线程 4
t4.setName("4");
t4.start();
Thread t5 = new Thread(T);//线程 5
t5.setName("5");
t5.start();
}
}
class threadT implements Runnable{ //实例化接口
private int tickets = 0;
@Override
public void run() {
boolean control = true;
while(control){
control = sell();//调用sell 方法,大家可以通过改变这个函数的调用,来看异步、同步的效果
}
} public boolean sell(){//异步线程机制,会被打断,所谓打断,就是会出现 线程1 卖了第2张票时,线程3也卖了第2 张
boolean control = true ;
if(tickets<100){
tickets ++;
//在函数内,如果没有具体的线程对象,就要使用静态方法 currentThread() 返回当前正在执行的线程对象的引用,在使用类方法
System.out.println(Thread.currentThread().getName()+":"+tickets);//同上
Thread.State state = Thread.currentThread().getState();//同上
System.out.println("State:"+state.toString());//输出当前的状态,正常是 runnable
}else{
control = false;
}
try{
Thread.sleep(1);
}catch (Exception e){
e.printStackTrace();
}
return control;
} //关键字 - synchronized 保护 当前 函数在执行时不被其他线程打断,同步线程机制
//整体同步,效率低
public synchronized boolean sell1(){
boolean control = true ;
if(tickets<100){
tickets ++;
//在函数内,如果没有具体的线程对象,就要使用静态方法 currentThread() 返回当前正在执行的线程对象的引用,在使用类方法
System.out.println(Thread.currentThread().getName()+":"+tickets);//同上
Thread.State state = Thread.currentThread().getState();//同上
// System.out.println("State:"+state.toString());
}else{
control = false;
}
try{
Thread.sleep(1);
}catch (Exception e){
e.printStackTrace();
}
return control;
}
//关键字 - synchronized 实质是一个对象锁 public boolean sell2(){ // 条件 关键字 - synchronized 保护 当前 函数在执行时不被其他线程打断,同步线程机制
boolean control = true ;
synchronized(this) { //仅仅同步会操作到的共同部分变量,tickets,这样避免同步整体,提高效率
if (tickets < 100) {
tickets++;
//在函数内,如果没有具体的线程对象,就要使用静态方法 currentThread() 返回当前正在执行的线程对象的引用,在使用类方法
System.out.println(Thread.currentThread().getName() + ":" + tickets);//同上
Thread.State state = Thread.currentThread().getState();//同上
// System.out.println("State:"+state.toString());
} else {
control = false;
}
}
try{
Thread.sleep(1);
}catch (Exception e){
e.printStackTrace();
}
return control;
}
}

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

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

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

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

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

notifyAll()则唤醒所有;

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

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

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

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

问题:

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

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

 package com.LGH.ew.view;

 /**
* Created by Administrator on 2015/4/25.
*/
public class Product { //生产者、消费者问题
public static void main(String[] args){
clerk c = new clerk();
Thread productT = new Thread(new Producer(c));//生产者线程
Thread consumerT = new Thread(new Consumer(c));//消费者线程
productT.start();
consumerT.start();
}
}
class clerk{ //店员
private int product = 0; //默认 0 个产品
public synchronized void addproduct(){ //生产出的产品,交给店员
if(this.product>=20){
try{
wait(); //产品过多,稍后再生产
}catch (Exception e){
e.printStackTrace();
}
}else{
product++;
System.out.println("生产者生产第"+product+"个产品。");
notifyAll(); //通知等待区的消费者可取产品
}
}
public synchronized void getproduct(){ //消费者从店员处取产品
if(this.product<=0){
try{
wait(); //缺货,稍后再取
}catch (Exception e){
e.printStackTrace();
}
}else{
System.out.println("消费者取走了第:" + product + "产品。");
product--;
notifyAll(); //通知等待取得生产者可以继续生产
}
}
} class Producer implements Runnable{ //生产者线程 private clerk c;
public Producer(clerk c){
this.c = c;
}
@Override
public void run() {
System.out.println("生产者开始生产产品。");
while(true){
try{
Thread.sleep((int)(Math.random()*10)*100);
}catch(Exception e){
e.printStackTrace();
}
c.addproduct(); //生产
}
}
} class Consumer implements Runnable{ //消费者线程 private clerk c ; public Consumer(clerk c){
this.c = c;
}
@Override
public void run() {
System.out.println("消费者开始取走产品。");
while(true){
try{
Thread.sleep((int)(Math.random()*10)*100);
}catch(Exception e){
e.printStackTrace();
}
c.getproduct(); //取产品
}
}
}

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

java 线程 Thread 使用介绍,包含wait(),notifyAll() 等函数使用介绍的更多相关文章

  1. Java线程Thread的状态解析以及状态转换分析 多线程中篇(七)

    线程与操作系统中线程(进程)的概念同根同源,尽管千差万别. 操作系统中有状态以及状态的切换,Java线程中照样也有. State 在Thread类中有内部类 枚举State,用于抽象描述Java线程的 ...

  2. java 线程Thread 技术--1.5Lock 与condition 演示生产者与消费模式

    在jdk 1.5 后,Java 引入了lock 锁来替代synchronized ,在使用中,lock锁的使用更加灵活,提供了灵活的 api ,不像传统的synchronized ,一旦进入synch ...

  3. java 线程Thread 技术--方法演示生产与消费模式

    利用wait 与notifyAll 方法进行演示生产与消费的模式的演示,我们两个线程负责生产,两个线程消费,只有生产了才能消费: 在effective Java 中有说过: 1. 在Java 中 ,使 ...

  4. java 线程之间通信以及notify与notifyAll区别。

    jvm多个线程间的通信是通过 线程的锁.条件语句.以及wait().notify()/notifyAll组成. 下面来实现一个启用多个线程来循环的输出两个不同的语句. package com.app. ...

  5. java 线程Thread 技术--volatile关键字

    java 语言中允许线程访问共享变量,为了保证共享变量能被准确和一致的更新,Java 语言提供了volatile 关键字,也就是我们所说的内存一致性: 问题抛出:(尝试去运行下面代码,以及将volat ...

  6. java 线程Thread 技术--1.5 Future与Callable

    Callable: 从官方文档说起: 通过实现callable 的called 方法可以使一个任务可以返回一个结果以及可能抛出一个异常: callable 与runnable 是相似的,可以被其他线程 ...

  7. java 线程Thread 技术--1.5 Executor Executors,ThreadPool,Queue

    Executors : Executors ,就是一个线程工具类:大部分操作线程的方法,都可以在这个工具类中就行创建,执行,调用一些线程的方法: Executor : 用于执行和提交一个runnabl ...

  8. java 线程Thread 技术--线程状态与同步问题

    线程技术第三篇: 线程的状态: 1. 创建状态: 当用new 操作符创建一个新的线程对象时,该线程就处于创建状态,系统不为它分配资源 2.可运行状态:当线程调用start 方法将为线程分配必须的系统资 ...

  9. java 线程Thread 技术--线程创建源码解释

    永远不要忘记最基础的东西,只有把最基础的知识打牢靠,才能够使你走的更远,我将从今天开始,进行线程知识的回顾,一些常用知识点,以及java1.5 引入的并发库,进行详细的讲解与总结 创建线程的目的是为了 ...

随机推荐

  1. flex的兼容

    父容器的 display 属性: .box{ display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit br ...

  2. Solve VS2010 Error "Exceptions has been thrown by the target of an invocation"

    Sometimes when you open a VS2010 project, an error window will pop up with the error message "E ...

  3. *HDU 2451 数学

    Simple Addition Expression Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  4. chrome浏览器js 导出excel

    <table id="table"> <tr> <th>ID</th> <th>姓名</th> <th ...

  5. 不需要sql进行计算数据的平均值、最大值、最小值、和

    介绍下SqlServer.前端js.后台C#三个阶段对均值.最大值.最小值.和计算int[] jisuan = {0, 1, 3, 5, 7,8 }; List<int> jisuan2 ...

  6. 移动Web触控事件总结

    移动web风风火火几多年,让我这个在Pc端漂流的前端er不免心生仰慕,的确入行几多年,也该是时候进军移动web了.移动web中踩到的第一个坑就是事件问题,所以在吸取众大神的经验后,特作总结以示后来者. ...

  7. C语言指针转换为intptr_t类型

    1.前言 今天在看代码时,发现将之一个指针赋值给一个intptr_t类型的变量.由于之前没有见过intptr_t这样数据类型,凭感觉认为intptr_t是int类型的指针.感觉很奇怪,为何要将一个指针 ...

  8. 深圳本土web前端经验交流

    群号:125776555  深圳本土web前端技术交流群 baidu tencent前端拒绝垃圾广告.吹水,欢迎讨论技术.跳槽经验期待您的加入 

  9. Git Shell 基本命令(官网脱水版)

    用户信息 当安装完 Git 应该做的第一件事就是设置你的用户名称与邮件地址. 这样做很重要,因为每一个 Git 的提交都会使用这些信息,并且它会写入到你的每一次提交中,不可更改: $ git conf ...

  10. EF:打开Oracle连接时报错

    基础提供程序在 Open 上失败. The underlying provider failed on Open. 解决:安装最新的ODTwithODAC121024.