android基础学习-java篇day9-step3-第五节:java线程

  • 目录

  • -线程的概念
  • -创建线程的两种方式
  • -线程的状态和生命周期
  • -sleep()和join方法
  • -线程的优先级
  • -同步
  • -线程间通信

什么是进程?

进程是一个运行的程序;

是指可执行程序并存放在计算机存储器的一个指令序列,它是一个动态执行的过程。

什么是线程?

线程是比进程还要小的运行单位,一个进程包含多个线程;

线程可以看做是一个子程序。

线程的创建 

  • 创建一个Thread类,或者一个Thread子类的对象
  1. 子类继承Thread类
  2. 在子类中重写run()方法
  3. 主方法main中调用start()方法启动线程
  • 创建一个实现Runnable接口的类的对象
  1. 通过线程实现类创建对象

  2. 将实现类的对象创建Thread的对象2

  3. 将实现类的对象创建Thread的对象2

Thread类

Thread是一个线程类,位于java.lang包下

构造方法 说明
Thread() 创建一个线程对象
Tread(String name) 创建一个具有指定名称的线程对象
Thread(Runnable target) 创建一个基于Runnable接口实现类的线程对象
Tread(Runnable target,String name) 创建一个基于Runnable接口实现,并且指定名称的线程对象

Thread类的常用方法

方法 说明
public void run() 线程相关的代码写在该方法中,一般需要重写
public void start() 启动线程的方法
public static void sleep(long m) 线程休眠m毫秒的方法
public void join() 优先执行调用join()方法的线程

Runnable接口

  • 只有一个run();方法
  • Runnable是java中实现线程的接口
  • 实现线程功能的类都必须实现该接口

1、线程的简单创建-继承Thread:

package com.demo.day9.thread;
/*
 * 通过基础Thread类的方式创建线程类,重写run()方法
 */
class MyThread extends Thread{
	public void run() {
		System.out.println(getName()+"该线程正在执行!");
	}
	
}

public class ThreadTest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println("主线程1");
		MyThread mt=new MyThread();//创建对象
		mt.start();//调用start()方法启动线程,执行run方法
		//start();只能执行一次
		System.out.println("主线程2");
		

	}

}

线程使用CPU的使用权是随机的:

package com.demo.day9.thread;

class MyThreadOne extends Thread {
	//构造方法,给线程取个名字
	public MyThreadOne(String name) {
		super(name);
	}
	public void run() {
		for(int i=1;i<10;i++) {
			System.out.println(getName()+"正在运行"+i+"次");
		}
	}
	
}
public class TreadOne {

	public static void main(String[] args) {
		//创建线程对象
		MyThreadOne mt1=new MyThreadOne("线程1");
		MyThreadOne mt2=new MyThreadOne("线程2");
		mt1.start();
		mt2.start();
		//线程获取CPU的使用权是随机的、执行结果随机

	} 

}

输出结果随机。。

2、线程创建-实现Runnale接口创建线程

为什么要实现Runnable接口?

  • java不支持多继承
  • 不打算重写Thread类的其他方法
  • java支持实现多接口

 简单案例:

package com.demo.day9.thread;
/*
 * 通过实现Runnable接口创建线程
 */
//创建线程实现类 PrintRunnale
 class PrintRunnable implements Runnable{

	@Override
	public void run() {
		//输出正在进行的线程
		int i=1;
		while(i<10)
			System.out.println(Thread.currentThread().getName()+"正在进行"+(i++)+"次");
		//Thread.currentThread().getName() 获取当前正在进行线程的名字
		
	}
	 
 }
public class MyRunnable {

	public static void main(String[] args) {
		//通过线程实现类创建对象
		PrintRunnable pt =new PrintRunnable();
		//将实现类的对象创建Thread的对象2
		Thread th=new Thread(pt);
		th.start();
		//将实现类的对象创建Thread的对象2
		//两个对象共用一个实现类对象
		Thread th2=new Thread(pt);
		th2.start();

	}

}

 线程的状态和生命周期

线程的五个状态

  • 新建(New)
  • 可运行(Runnable)(又叫就绪)
  • 正在运行状态(Running)
  • 阻塞(Blocked)
  • 终止(Dead)

线程的生命周期

sleep方法的应用

  • Thread类的方法

public static void sleep(long millis)

  • 作用:在指定的毫秒数内让正在执行的线程休眠,暂停执行
  • 参数为休眠的时间,单位是毫秒
package com.demo.day9.thread;
//通过实现Runnable接口创建线程
class MyThreadTwo implements Runnable{

	@Override
	public void run() {
		for(int i=1;i<15;i++) {
			System.out.println(Thread.currentThread().getName()+"正在进行"+i+"次");
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}//让线程休眠1秒
		}
		
	}
	
}

public class ThreadTwo {

	public static void main(String[] args) {
		// 创建线程类对象
		MyThreadTwo mt=new MyThreadTwo();
		//通过线程类对象创建Thread类对象调用start方法
		Thread th=new Thread(mt);
		th.start();

}
}

join方法的使用(强制CPU控制权)

  • Thread类的方法

public final void join()

  • 作用:等待调用该方法的线程结束后,之后的线程才能执行

public final void join(long millis)

作用:等待该线程终止的最长时间为millis毫秒,无论该线程是否执行完,要释放CPU控制权

 

线程的优先级

  • java为线程类提供了10个优先级
  • 优先级可以用整数1-10表示,超过范围会抛出异常
  • 主线程默认优先级为5
  • 优先级常量
  • -MAX_PRIORITY:线程的最高优先级10
  • -MIN_PROIRITY:线程的最低优先级1
  • -NORM_PROIRITY:线程的默认优先级
  • 优先级相关的方法
方法 说明
public int getPriority() 获取线程的优先级的方法
public void setPriority() 设置线程的优先级的方法

线程同步synchronized

多线程运行存在的问题

  • 各个线程是通过竞争CPU时间而获得运行机会的

  • 各线程什么时候得到CPU时间,占用多久,是不可预测的
  • 一个正在运行着的线程在什么地方被暂停是不确定的

银行存取款案例:

Bank.java

package com.demo.day9.thread;

public class Bank {
	private int balance;//账户余额
	private String account;//账户
	//带参构造,为变量赋值
	public Bank(String account,int balance) {
		this.setAccount(account);
		this.setBalance(balance);
	}

	public int getBalance() {
		return balance;
	}

	public void setBalance(int balance) {
		this.balance = balance;
	}

	public String getAccount() {
		return account;
	}

	public void setAccount(String account) {
		this.account = account;
	}
	//重写toString
	public String toString() {
		
		return "账户为:"+this.getAccount()+" "+"余额为:"+this.getBalance();
		
	}
    //存钱的方法
	public void savaAccount(){
		synchronized (this){//同步,执行这个线程,不允许其他线程抢占CPU
		int balance=getBalance();//获取当前账户余额
		try {
			Thread.sleep(1000);//让线程休眠1秒
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		balance+=100;//存入100元
		setBalance(balance);//
		System.out.println("存款后账户余额:"+balance);
		}
	}
	public void  drawAccouct() {
		int balance=getBalance();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		balance-=200;//取款200
		setBalance(balance);
		System.out.println("取款后账户余额:"+balance);
	
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}

SaveAccount.java

package com.demo.day9.thread;
/*
 * 存款
 */
//通过实现Runnable接口来创建线程
public class SaveAccount implements Runnable{
	Bank bank;//创建Bank对象

	public SaveAccount(Bank bank) {
		super();
		this.bank = bank;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		bank.savaAccount();
	}
	

}

DrawAccount.java

package com.demo.day9.thread;
/*
 * 取款
 */
public class DrawAccount implements Runnable {
	Bank bank;
	public DrawAccount(Bank bank) {
		super();
		this.bank = bank;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		bank.drawAccouct();
	}

}

Test.java

package com.demo.day9.thread;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Bank bank=new Bank("1001",1000);//创建对象bank
		SaveAccount sa=new SaveAccount(bank);
		DrawAccount da=new DrawAccount(bank);
		//创建线程对象
		Thread save =new Thread(sa);
		Thread draw =new Thread(da);
		save.run();
		draw.run();
		try {
			draw.join();
			save.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println(bank);

	}

}

输出:

存款后账户余额:1100
取款后账户余额:900
账户为:1001 余额为:900

银行存取款问题

  • 为了保证在存款或取款的时候,不允许其他线程进行操作
  • 需要将Bank对象进行锁定
  • 使用关键字synchronized实现

同步

synchronized关键字用在

成员方法

public synchronized void saveAccount(){}

静态方法

public static synchronized void saveAccount(){}

语句块

synchronize (obj){.....}

线程间通信

  • wait()方法:中断方法的执行,是线程等待
  • 如果不配合notify方法使用,可能使两个线程都处于等待状态,陷入死锁
  • notify()方法:唤醒处于等待的某个线程,使其等待结束
  • notifyAll()方法:唤醒所有处于等待的线程,使他们结束等待

 案例要求:

  • 生产者每生产一个后,消费者消费一个;
  • 不能存在生产者生产一个,消费者消费两个
  • 或者生产者生产两个,消费者消费一个

Queue.java

package com.demo.day9.thread;

public class Queue {
private int n;
boolean flag=false;//设默认flag为false。默认先生产
public synchronized int getN() {
	if(!flag) {//执行等待
		try {
			wait();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	System.out.println("消费"+n);
	flag=false;//消费完毕,再flag重新赋值为false
	notifyAll();//与wait()搭配使用,唤醒所有线程
	return n;
}
public synchronized void setN(int n) {
	if(flag) {//如果容器里有数据,flag为true,执行等待
		try {
			wait();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	System.out.println("生产"+n);
	this.n = n;
	flag=true;//生产完毕,重新另flag为true
	notifyAll();//唤醒所有的线程
}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
	

}

Producer.java

package com.demo.day9.thread;

public class Producer implements Runnable{
  Queue queue;
  Producer( Queue queue){
	  this.setQueue(queue);
  }
  
  
	public Queue getQueue() {
	return queue;
}

public void setQueue(Queue queue) {
	this.queue = queue;
}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		int i=0;
		while(true) {
			queue.setN(i++);
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	

}

Consumer.java

package com.demo.day9.thread;

public class Consumer implements Runnable {
	Queue queue;

	public Consumer(Queue queue) {
		super();
		this.queue = queue;
	}


 
	@Override
	public void run() {
	while(true)
	{
		queue.getN();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	}
	

}

TestQ.java

package com.demo.day9.thread;

public class TestQ {

	public static void main(String[] args) {
		// 创建Queue对象
		Queue queue=new Queue();
		//创建对象
		Producer p1=new Producer(queue);
		Consumer c1=new Consumer(queue);
		//实现上面创建的对象
//		Thread p=new Thread(p1);
//		Thread c=new Thread(c1);
//		p.start();
//		c.start();
		new Thread(new Producer(queue)).start();
		new Thread(new Consumer(queue)).start();
		

	}

}

输出结果:

生产0
消费0
生产1
消费1
生产2
消费2
生产3
消费3
生产4
消费4
生产5
消费5
生产6....

综合案例:

生成天气数据,然后显示出来

Weather.java

package com.test;
/*
 * 这是一个天气类Weather,用于温度和湿度数据的存放和读取
 */
public class Weather {
	private int temperature;//温度
	private int humidity;//湿度
	boolean flag=true;
	//带参构造
	Weather(){
		this.setHumidity(humidity);
		this.setTemperature(temperature);
	}
	//生成天气数据的方法
	public synchronized void generateWeather(int temp,int hum) {
		if(!flag)//如果flag=false
		{
		try {
			wait();//如果为flag为假让它等待
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		}
		this.setHumidity(hum);
		this.setTemperature(temp);
		System.out.println("生成天气数据:"+"[温度:"+this.getTemperature()+",湿度:"+this.getHumidity()+"]");
		notifyAll();//唤醒所有等待
		flag=false;//重新flag赋值为false
		}
	//显示天气数据的方法
	public  synchronized void readWeather() {
		if(flag) {//如果为真等待
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		System.out.println("读取天气数据:"+"[温度:"+this.getTemperature()+",湿度:"+this.getHumidity()+"]");
		notifyAll();//唤醒所有等待
		flag=true;//重新flag赋值为false
	}

	public int getTemperature() {
		return temperature;
	}

	public void setTemperature(int temperature) {
		this.temperature = temperature;
	}

	public int getHumidity() {
		return humidity;
	}

	public void setHumidity(int humidity) {
		this.humidity = humidity;
	}
	

}

GenerateWeather.java

package com.test;
/*
 * 这个是个线程类,用于生成天气数据,模拟生成100次
 */
public class GenerateWeather implements Runnable{
	Weather weather;
	
	GenerateWeather(Weather weather){
		this.weather=weather;
		
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

	@Override
	public void run() {
		int i=1;
		int temp=32;
		int hum=26;
		while(i<100) {
			temp+=1;
			hum+=1;
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			weather.generateWeather(temp,hum);
			i++;
		}
	}
	

}

ReadWeather.java

package com.test;
/*
 * 这是一个线程类,用于读取天气数据
 */
public class ReadWeather implements Runnable {
	
	Weather weather;
	ReadWeather(Weather weather){
		this.weather=weather;	
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub
		int i=1;
		while(i<100) {
			weather.readWeather();
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			i++;
		}
	}
	

	
}

WeatherTest.java

package com.test;

public class WeatherTest {

	public static void main(String[] args) {
		Weather wt=new Weather();
		new Thread(new GenerateWeather(wt)).start();
		new Thread(new ReadWeather(wt)).start();


	}

}

显示结果

生成天气数据:[温度:33,湿度:27]
读取天气数据:[温度:33,湿度:27]
生成天气数据:[温度:34,湿度:28]
读取天气数据:[温度:34,湿度:28]
生成天气数据:[温度:35,湿度:29]
读取天气数据:[温度:35,湿度:29]
生成天气数据:[温度:36,湿度:30]
读取天气数据:[温度:36,湿度:30]
生成天气数据:[温度:37,湿度:31]
读取天气数据:[温度:37,湿度:31]
生成天气数据:[温度:38,湿度:32]
读取天气数据:[温度:38,湿度:32]
.......

猜你喜欢

转载自blog.csdn.net/qq_17846019/article/details/82655719
今日推荐