多线程技术基础

本文详细介绍了Java中实现多线程的两种方式,即继承Thread类和实现Runnable接口,并展示了如何获取和设置线程信息、终止线程。接着讲解了线程的join方法用于线程联合,以及线程同步的概念,通过synchronized关键字避免并发问题。最后,通过生产者-消费者模型演示了wait()和notify()方法在多线程协作中的应用。
摘要由CSDN通过智能技术生成

基本概念

  1. 进程与线程:举个例子,电脑上运行的各个应用程序为进程,那么在一个应用程序中的运行的为线程。执行的程序为进程,一个进可以产生多个线程。
  2. 多线程:同时多条线程同时运行,就好像你个人可以边吃饭边听歌一样。

实现多线程的两种方法

两种方法

  1. 用extends继承Thread类
  2. 用implements实现Runnable接口
    方法一`
public class TestThread extends Thread {
	//重写run方法
	public void run() {
		for(int i=0;i<10;i++) {
			System.out.println("输出:"+i);
		}
	}
	public static void main(String[] args) {
		TestThread thread=new TestThread();
		thread.start();
	}
}

方法二

public class TestThread2 implements Runnable{
	public void run() {
		for(int i=0;i<10;i++) {
			System.out.println("2号输出"+i);
		}
	}
	public static void main(String[] args) {//将实现了Runnable类的对象作为参数传入
		Thread thread = new Thread(new TestThread2());
		thread.start();
	}
}

画重点:实现Runnable时将这个实现类的对象作为参数传入到新建的线程对象在,从而可以调用实现类中的方法。

获得线程的基本信息获取

  1. 线程的命名,setname()
  2. 得到线程的名字,getname()
  3. 判断线程是否“活着”,isAlive()
  4. 取得线程本身的方法,currentThread()
  5. 设置线程优先级,setPriority(),1-10级,级数越高,运行可能高,并不是一定先运行
public class TestThread3 extends Thread{
	public void run() {
		for(int i = 0;i<5;i++) {//取正在运行的线程,并得到他的名字
			System.out.println(Thread.currentThread().getName()+"输出"+i);
		}
	}
	public static void main(String[] args) {
		TestThread3 thread1=new TestThread3();
		thread1.setName("线程1");
		TestThread3 thread2=new TestThread3();
		thread2.setName("线程2");
		System.out.println("thread1的名字为"+thread1.getName());
		System.out.println("判断thread2是否还存在"+thread2.isAlive());
		thread1.setPriority(10);
		thread1.start();
		thread2.start();
	}

}

终止线程的方法

思路:设置一个条件,while判断,条件满足时,可以运行run方法里的方法体,条件不满足时,则不运行

public class TestThread4 implements Runnable{
	boolean a=true;
	public void run() {
		int i=0;
		System.out.println("ok");
		while(a) {
			System.out.println("线程在运行"+(i++));
		}
		System.out.println("线程结束");
	}
	public void cease() {
		a=false;
	}
	public static void main(String[] args) {
		TestThread4 ttt=new TestThread4();
		Thread thread=new Thread(ttt);
		thread.start();
		for(int i=0;i<20;i++) {
			System.out.println("主线程运行"+i);
		}
		ttt.cease();
		System.out.println("线程该停了");	
	}
}

线程联合

两个线程同时运行,相互嵌合,当其中一个运行完成之后另外一个才能继续运行。
方法:线程.join()

public class TestThread5 {

	public static void main(String[] args) {
		A thread1=new A();
		thread1.start();
		try {
			thread1.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("A接过了B买的东西");//-------------------②
	}

}
class A extends Thread{
	public void run() {
		System.out.println("A让B去买东西");
		B thread2=new B();
		thread2.start();
		try {
			thread2.join();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("B买好了");//----------①
	}
}

class B extends Thread{
	public void run() {
		System.out.println("B买东西要四分钟");	
		for(int i=0;i<4;i++) {
			System.out.println("已经过了"+i+"分钟");
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
}

运行后会发现,输出语句①定要thread2运行完后才会运行,输出语句②要thread1运行完后才会运行

线程同步

同步方法:synchronized()

public class TestSync {

	public static void main(String[] args) {
		Account a1=new Account(100,"高");
		Drawing draw1=new Drawing(80,a1);
		Drawing draw2=new Drawing(80,a1);
		draw1.start();
		draw2.start();
	}

}
class Account {
	int money;
	String name;
	public Account(int money,String name) {
		this.name=name;
		this.money=money;
	}
}
class Drawing extends Thread{
	int drawingNum;//取多少钱
	Account account;
	int total;//取钱总数
	public Drawing(int drawingNum,Account account) {
		this.account=account;
		this.drawingNum=drawingNum;
	}
	public void run() {
			if(account.money-drawingNum<0) {
				System.out.println(this.getName()+"取款,余额不足,取款失败!!!");
				return;
			}
			try {
				Thread.sleep(30);
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
			account.money-=drawingNum;
			total+=drawingNum;
			System.out.println(this.getName()+"账户余额"+account.money);
			System.out.println(this.getName()+"共取了"+total);
	}
}

在这里插入图片描述当两个线程同时使用一个空间是,会发生问题,就如上面,thread0和thread1同时在只有100的银行里取钱,却取出来总和160的钱,解决这个问题的方法是在关键部分使用synchronized()方法,在synchronized块里面只能有一个线程进去。

public void run() {
	synchronized(account) {
			if(account.money-drawingNum<0) {
				System.out.println(this.getName()+"取款,余额不足,取款失败!!!");
				return;
			}
			try {
				Thread.sleep(30);
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
			account.money-=drawingNum;
			total+=drawingNum;
			System.out.println(this.getName()+"账户余额"+account.money);
			System.out.println(this.getName()+"共取了"+total);
	}
	}

生产者——消费者模型

  1. 方法:wait();notify();
    一个是等待,一个是通知,当线程运行到wait是,只有接收到一个notify的通知时才能继续运行,在线程并发协作时,需要用到这两个方法。
  2. 生产者——消费者模型,设计三个类:
    生产者类:生产数据;
    消费者类:取出数据;
    存储类:存储数据;
    给一个最大的存储量和初始数据量,通过生产者、消费者的生产、取出变换存储数据量,数据达到最大值时,生产者wait,知道得到消费者通知notify()已经消费时,继续生产,反之亦然。
public class Wait_notify {
	public static void main(String[] args) {
		Bank bank =new Bank();
		//生产者线程
		produce thread0=new produce(bank);
		produce thread1=new produce(bank);
		produce thread2=new produce(bank);
	    //消费者线程
		consumer thread3=new consumer(bank);
		consumer thread4=new consumer(bank);
		consumer thread5=new consumer(bank);
		thread0.start();
		thread1.start();
		thread2.start();
		thread3.start();
		thread4.start();
		thread5.start();
	}
}
class Bank {
	private int total=6;
	private int max =10;
	
	public synchronized void remove () {
		//可消费
		if(total>0) {
			total--;
			System.out.println(Thread.currentThread().getName()+"消费一件资源,此时为"
					+total+"件"		);
			this.notifyAll();
		}else {
			//等待增加
			try {
				System.out.println("已经没有库存,等待生产者增加");
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	public synchronized void add() {
		//数量小于最大值,增加
		if(total<max) {
			total++;
			System.out.println(Thread.currentThread().getName()+"生产一件资源,此时为"
					+total+"件"		);
			this.notifyAll();
		}else {
		//数量已满,等待消费
			try {
				System.out.println("数量已满,等待消费者消费");
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}	
}
class produce extends Thread {
	private Bank bank;
    produce(Bank bank) {
		this.bank=bank;
	}
	public void run() {
		while(true) {
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			bank.add();
		}
	}
}
class consumer extends Thread{
	private Bank bank;
    consumer(Bank bank) {
		this.bank=bank;
	}
	public void run() {
		while(true) {
			try {
				Thread.sleep(300);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			bank.remove();
		}
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北极,南极

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值