Thread线程

多线程
一、 什么是线程
        线程是程序的最小单位,相对独立可调配的单元,是CPU最小的基本单位
在同一个程序不同的线程完成功能,称为多线程,软件中最小的单位就是线程


二、线程、   进程 、程序之间的关系 
程序 :程序就是一段静态代码,是应用程序的蓝本
进程:进程就是程序的一次正常运行,从代码的第一句执行到最后一句,整个过程就是进程的生命 周期
线程:进程中独立、 可调配的最小执行单元就是线程, 进程由多个线程组成

程序与进程的关系
一个程序一般只有一个进程, 单一个程序可以有多个进程
一个进程只能属于一个程序

进程与线程的关系
一个进程拥有多个线程
一个线程只能属于一个进程

java的应用程序主线程就是main方法,程序只有一个主线程,其他的都是子线程

CPU就是用来处理线程的
 
三、线程创建
在java中线程的创建方式有两种,分别如下:
1、创建一个类继承Thread类
Thread  thread = new Thread();
thread.start();
2、创建一个类实现Runnable接口
Thread thread  = new Thread( new  Runnable);
thread.start();

使用Runnab               

Thread类实现了Runnable接口

package com.tencent.thread;
/**
 * 线程的创建
 * @author Ricardo.M.Y   2018年5月14日
 */
public class ThreadCreate {
	
	public static void main(String[] args) {
		LeftThread left = new LeftThread();   			  //分配内存空间
		left.start();														//启动线程
		/*
		Thread right =new  Thread(new RightThread());
		right.start();*/
		RightThread right = new RightThread();   			  //分配内存空间
		right.start();		
		
	}

}
/**
 * 左线程
 * @author Ricardo.M.Y   2018年5月14日
 */
class LeftThread extends Thread{
	
		@Override
		public void run() {
			while("1".equals("1")){
				System.out.println("我是光明左使杨逍");
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				
			}
			
		}
	
}
/**
 * 右线程
 * @author Ricardo.M.Y   2018年5月14日
 */
class RightThread extends Thread{
	
	@Override
	public void run() {
		while("1".equals("1")){
			System.out.println("我是光明右使范遥");
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
	}
	
}

/**
 * 左线程
 * @author Ricardo.M.Y   2018年5月14日
 */
/*class RightThread implements Runnable{

	@Override
	public void run() {
		while(true){
			System.out.println("我是光明右使范遥");
		}
		
	}
	
}*/


*O*四、线程的生命周期
1、创建:线程构造
2、启动:线程调用了start()方法,去CPU排队
3、运行:线程占用CPU,进入run()方法
4、中断:在run()方法遇到sleep()与wait()方法,线程会中断,让出CPU资源
5、死亡:线程运行完run()方法

*O* 五、线程状态
1、NEW(新建状态):线程对象已经创建好,但是没有被启动
2、RUNNABLE(可运行状态):线程对象调用start( ) 到进入run()都是可运行状态
3、BLOCKED(阻塞状态):线程对象遇到sleep()
4、WAITING(等待状态):线程对象遇到wait() 

5、TERMINATED(死亡状态):线程对象运行完run() 方法

package com.tencent.thread;

/**
 * 线程状态
 * @author Ricardo.M.Y   2018年5月14日
 */
public class ThreadState {

		public static void main(String[] args){
			State s=  new State();
			System.out.println(s.getState());
			s.start();
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(s.getState());
		}
}

class State extends Thread{
	
	@Override
	public void run() {
			System.out.println(this.getState());
	}
}


六、线程的休眠(sleep)与唤醒(interrupt)
当一个线程对象在sleep的时候,可以通过interrupt()方法进行强制唤醒,

唤醒后会抛出InterruptedException异常

      线程的挂起(wait)与恢复(notifyAll)
wait()  线程挂起
notifyAll() 唤醒所有挂起线程
notify() 唤醒单个线程

以上三个方法是Object类的方法 ()
wait()必须结合同步锁使用,否则会发生异常

package com.tencent.thread;
/**
 * 测试线程唤醒
 * 学生线程、 老师线程
 * 上课的时候学生睡觉,老师说:上课!上课! 上课!
 * 学生强行被唤醒,然后认真听课
 * @author Ricardo.M.Y   2018年5月14日
 */
public class InterruptTest {

	public static void main(String[] args) {

			Thread t = new Thread(new School());
			t.start();
	}
	
}

class School implements Runnable{
	
	private Thread student,teacher;

	public School(){
		student = new Thread(this);
		student.setName("姜维");
		student.setPriority(10);
		student.start();

		teacher = new Thread(this);
		teacher.setName("诸葛亮");
		teacher.setPriority(1);
		teacher.start();
	}
	
	
	public void run() {
		//Thread.currentThread() 获取当前正在占用cpu的线程
		if(Thread.currentThread() == student){
			System.out.println(student.getName() +"正在睡觉" );
			try {
				Thread.sleep(1000*60*60);
			} catch (InterruptedException e) {
				//e.printStackTrace();
				System.out.println(student.getName()+"被"+teacher.getName()+"叫醒了");
				System.out.println(student.getName()+"知道错了,下次再也不敢了!");
			}
		}
		if(Thread.currentThread() == teacher){
			for(int i=0;i<3;i++){
					System.out.println(teacher.getName()+"说:上课!");
			}
			//唤醒学生
			student.interrupt();
		}
			
		
	}
}

package com.tencent.thread;
/**
 * 线程的挂起(wait)
 * eg :员工与老板的案例
 * 员工工作八小时后,跟老板说说一句:好累啊! 我去休息一下
 * 老板开始数数,从1数到10,然后员工起来工作
 * @author Ricardo.M.Y   2018年5月14日
 */
public class WaitTest {

	public static void main(String[] args) {
		new Company();
	}
}

/**
 * 公司
 */
class Company implements Runnable{
	
	private Thread staff,boss;
	
	private int hour=0;	//工作时间
	
	private int num=0;  //老板数数  
	
	public Company(){
		staff=new Thread(this,"乃亮");
		staff.setPriority(10);
		staff.start();
		boss = new Thread(this,"pgOne");
		boss.setPriority(1);
		boss.start();
	}
	@Override
	public void run() {
			working();
	}
	//工作
	private synchronized void working(){
		if(Thread.currentThread() == staff){
			while(true){
				hour++;
				System.out.println("老板,我是"+staff.getName()+",现在"+hour+"点了,我还在工作!");
				if(hour ==8){
					System.out.println("老板,我好累啊! 我去休息了");
					try {
						this.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					hour=0;
					this.notifyAll();
				}
			}
		}
		if(Thread.currentThread() == boss){
			while(true){
				num++;
				System.out.println("我是"+boss.getName()+"老板,开始数数"+num);
				if(num==10){
					//唤醒员工
					this.notifyAll();
					try {
						this.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					num=0;
				}
			}
			
		}
	}
	
	
}
	


七、线程常用的方法

start() 启动线程
run() 线程占用CPU时执行的方法
getState()         获取线程的状态
setName() 设置线程名称
getName( ) 获取线程名称
setPirority() 设置线程的优先级参数的数字越大表示优先级越高(0~10)
currentThread() 获取当前占用CPU的线程 ,静态方法
sleep() 线程 休眠
interrupt() 唤醒休眠的线程

 *O* 八 、线程同步
   1、什么是线程不安全
    线程不安全必须满足必须满足三个条件:
a、必须是同一个对象
b、必须是多个线程操作
c、改变共同的全局属性值

在方法上增加synchronize关键字,增加同步锁之后,方法调用会变慢,编程重量级方法

线程安全 线程不安全
StringBuffer      StringBuilder
Vector ArrayList
HashTable HashMap
package com.tencent.thread;
/**
 * 线程同步
 * eg、银行有出纳与会计两个线程
 * 比如:有个账户有50w,每天出纳取钱两次,每次20万
 * 会计每天存钱三次,每次30万
 * 看一周后的账单
 * @author Ricardo.M.Y   2018年5月14日
 */
public class BankTest {

	public static void main(String[] args) {
 		Thread th = new Thread(new Bank());
		th.start();
			
	}
}

class Bank implements Runnable{
	
	private Thread cashier,accountant;			//两个线程
	
	private int deposit =50;	//存款
	
	public Bank(){
		
		cashier = new Thread(this,"出纳");
		cashier.setPriority(10);
		cashier.start();
		
		accountant = new Thread(this,"会计");
		accountant.setPriority(1);
		accountant.start();
		
	}
	
	@Override
	public void run() {
		
		//业务逻辑
		for(int i = 1;i<=5;i++){
			if(Thread.currentThread() == cashier){
				//取钱
				access(i,20);
				
			}
			if(Thread.currentThread() ==accountant){
				//存钱
				access(i,30);
			}
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 存取钱
	 * @author Ricardo.M.Y   2018年5月14日
	 * @param day
	 * @param money
	 */
	private synchronized void  access(int day,double money){
		//出纳
		if(Thread.currentThread() == cashier){
		System.out.println("今天星期"+day+",我是"+cashier.getName());
			for(int i=0;i<2;i++){
				deposit-=money;
				System.out.println("当前余额"+deposit+"万元");
			}
		}
		//会计
		if(Thread.currentThread() == accountant){
			System.out.println("今天星期"+day+",我是"+accountant.getName());
			for(int i=0;i<3;i++){
				deposit+=money;
				System.out.println("当前余额"+deposit+"万元");
			}
		}
	}
	
	

}

经典案例:

    

1.  编写多线程应用程序,模拟多个人通过一个山洞的模拟。这个山洞每次只能通过一个人,每个人通过山洞的时间为5秒,随机生成10个人,同时准备过此山洞,显示一下每次通过山洞人的姓名。

 

 2.编写线程同步模拟应用程序:

   (1) 大气环境数据为:温度,湿度,风速。

   (2) 一个大气环境传感器测量环境数据需要5秒时间。

   (3) 一个计算机读取传感器的环境数据需要0.01秒时间。

   模拟一个计算机读取大气环境传感器的读取的随机的温度,湿度和风速的100次。

package com.tencent.work;

/**
 * 山洞类
 * 2018年5月15日
 */
public class Cave {

	/**
	 * 过山洞
	 * 2018年5月15日
	 */
	public synchronized void pass() {
		String name = Thread.currentThread().getName();
		System.out.println(name + "正在进山洞");
		try {
			Thread.sleep(5 * 1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(name + "通过山洞");
	}
	
	public static void main(String[] args) {
		Cave cave = new Cave();
		for(int i=1; i<=10; i++) {
			Person p = new Person(cave,"葫芦娃" + i + "号");
			p.start();
		}
	}
}

class Person extends Thread {
	private Cave cave;
	
	public Person(Cave cave, String name) {
		this.cave = cave;
		this.setName(name);
	}
	
	@Override
	public void run() {
		cave.pass();
	}
}

package com.tencent.work;

import java.text.DecimalFormat;

/**
 *  编写线程同步模拟应用程序:
   (1) 大气环境数据为:温度,湿度,风速。		大气环境		Atmospheric environment
   (2) 一个大气环境传感器测量环境数据需要5秒时间。
   (3) 一个计算机读取传感器的环境数据需要0.01秒时间。
   模拟一个计算机读取大气环境传感器的读取的随机的温度,湿度和风速的100次。
 * @author Ricardo.M.Y   2018年5月15日
 */
public class Environment {
	
	
	public static void main(String[] args) {
		System.out.println("请稍等,传感器正在测量环境数据(5秒)");
		Environment en = new Environment();
		for(int i =1;i<=100;i++){
			Test t = new Test(en);
			t.start();
		}
		
		
	}
	
	/**
	 * 测量
	 * @author Ricardo.M.Y   2018年5月15日
	 */
	public synchronized void measure(){
		//一个大气环境传感器测量环境数据需要5秒时间。
		try {
			Thread.sleep(1000*5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//温度,湿度,风速
		DecimalFormat df = new DecimalFormat("#.0");				//取小数点后几位
		String  temperature =df.format(Math.random()*100);		
		String humidity =df.format(Math.random()*100);
		String speed = df.format(Math.random()*100);
		//一个计算机读取传感器的环境数据需要0.01秒时间。
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//打印
		System.out.println("温度:"+temperature+"\t 湿度:"+humidity+"\t 风速:"+speed);
	}
}
		class Test extends Thread {
			private Environment en;
			
			public Test(Environment en){
				this.en = en;
			}
			@Override
			public void run() {
				en.measure();
			}
		}

































阅读更多
文章标签: Thread
个人分类: 框架
想对作者说点什么? 我来说一句

java最新多线程编程

2011年01月20日 615KB 下载

关于线程管理 thread delphi

2010年04月21日 560KB 下载

线程thread demo

2011年12月08日 32KB 下载

线程学习一 源代码

2012年07月03日 1.8MB 下载

Thread实现多线程

2015年05月01日 1KB 下载

java线程Thread

2011年12月26日 7KB 下载

Java课件\thread.rar

2012年03月16日 226KB 下载

没有更多推荐了,返回首页

不良信息举报

Thread线程

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭