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();
			}
		}

































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值