(原创,转载请说明出处!谢谢--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. HTML5将图片转化成字符画

    HTML5将图片转化成字符画 字符画大家一定非常熟悉了,那么如何把一张现有的图片转成字符画呢?HTML5让这个可能变成了现实,通过canvas,可以很轻松实现这个功能.其实原理很简单:扫描图片相应位置 ...

  2. 移动前端不得不了解的html5 head 头标签

    本文主要内容来自一丝的常用的 HTML 头部标签和百度FEX的HTML head 头标签. 移动端的工作已经越来越成为前端工作的重要内容,除了平常的项目开发,HTML 头部标签功能,特别是meta标签 ...

  3. yii笔一----基础,安装,结构,增删改查基本操作

    从yii中文站开始http://www.yiichina.com/ Yii 是一个高性能,基于组件的 PHP 框架 一. 1.安装yii方式 composer安装或者下载一份应用程序模板.刚开始学习, ...

  4. backbone入门示例

    最近因为有个项目需要用backbone+mui  所以最近入坑backbone. Backbonejs有几个重要的概念,先介绍一下:Model,Collection,View,Router.其中Mod ...

  5. Android动画

    [浅谈Android动画] 总共四种:Tween Animation变换动画.Frame Animation帧动画 Layout Animation布局动画.Property Animation 属性 ...

  6. 循序渐进做项目系列(3):迷你QQ篇(1)——实现客户端互相聊天

    <循序渐进做项目系列迷你QQ篇>将陆续介绍客户端聊天,文件传输,加好友,群聊,包括语音聊天,视频聊天,远程桌面等等需求如何实现,感兴趣的朋友可以持续关注.考虑到某些需求较为复杂,本系列采用 ...

  7. 剑指Offer面试题:7.旋转数组的最小数字

    一.题目:旋转数组的最小数字 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2 ...

  8. WebApiThrottle限流框架使用手册

    阅读目录: 介绍 基于IP全局限流 基于IP的端点限流 基于IP和客户端key的端点限流 IP和客户端key的白名单 IP和客户端key自定义限制频率 端点自定义限制频率 关于被拒请求的计数器 在we ...

  9. 求两点之间最短路径-Dijkstra算法

     Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.D ...

  10. 在C#代码中应用Log4Net(一)简单使用Log4Net

    首先让我们先把Log4Net跑起来,示例代码在文章最后面可以下载 1.先把Log4Net引入到工程中,为了演示方便,我们先建立一个winform程序.在程序的根目录下面,建立一个Libs文件夹,以便存 ...