欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

用多线程来解决多人分零食问题

程序员文章站 2022-04-21 10:41:07
x# 多线程1.线程的创建和启动线程的创建和启动有两种方式:1,继承于线程类Thread来创建线程2,利用实现于Runnable的方式创建线程1)继承Thread类用法:先自定一个类,然后继承于Thread类,在自定义类中要覆盖Thread类中的run()方法,run()方法中写自己需要开启线程的代码,之后在主方法中创建自定义类的对象,调用对象中继承父类的start方法,底层会自动调用自定义类中的run方法,开启线程.不能直接调用run方法,因为这样只是运行一个普通方法,不会开启多个线程.具体代码...

x# 用多线程来解决多人分零食问题

1.线程的创建和启动

线程的创建和启动有两种方式:1,继承于线程类Thread来创建线程2,利用实现于Runnable的方式创建线程

1)继承Thread类

用法:先自定一个类,然后继承于Thread类,在自定义类中要覆盖Thread类中的run()方法,run()方法中写自己需要开启线程的代码,之后在主方法中创建自定义类的对象,调用对象中继承父类的start方法,底层会自动调用自定义类中的run方法,开启线程.不能直接调用run方法,因为这样只是运行一个普通方法,不会开启多个线程.

具体代码:

class Apple extends Thread{

public void run(){     
//线程体,线程启动时,会自动调用本方法,所以这里是写代码的主体部分
}}
public class ThreadDemo{
public static void main(String[] args){
	Apple a=new Apple();
	a.start();
}
}

2)实现于Runnable接口来创建线程

用法:先创建一个自定义类,让它实现于Runnable接口,类中定义一个覆盖的run方法,用于写自己线程的具体代码,在主方法中创建一个自定义类对象,然后再创建一个Thread类对象,将自定义对象引入Thread类的有参构造器中,只需调用Thread对象的start方法就可以开启自定义类的线程了.

具体代码;

class Apple1 implements Runnable{
public void run(){
//线程体,线程启动时,会自动调用本方法,所以这里是写代码的主体部分
}
}
public class RunnableDemo{
public static void main(String[] args){
Apple1 a=new Apple1();
Thread t=new Thread(a);
t.start();
}
}

2.继承方式和实现方式的差异

当拥有多线程的时候,我们会发现一个问题:继承方式创建多线程时会创建多个对象,当面对多线程共享同一个资源的问题时,创建多个对象意味着有多个资源,例如三个人一起分50包零食时,用继承方式会创建150包零食,这样就没有达到自己想要的目的(除了把成员变量用static修饰),而用实现方式可以创建三个线程同时引用一个对象来进行操作,从这方面来看实现方式比继承方式更能体现出多线程.

具体代码

继承方式来完成三个人分零食
public class ThreadDemo{
	public static void main(String[] args){
	new Food("小明").start;  //运行三个线程
	new Food("小红").start;
	new Food("小胖").start;
	}
}
class Food extends Thread{
	private int num=50;  //定义零食的数量
	public Food(String name){   //这时使用子类构造器把名字传入到父类构造器中
		super(name);
	}
	public void run(){
	for(int i=o;i<50;i++)
	if(num>0){
	System.out.println(super.getName()+"分了第"+num+"包零食");使用super.getName获取线程的名字
	num--;   //每吃一次都会少一包零食
	}
	}
}
实现方式来完成三个人分零食
public class RunnableDemo{
	public static void main(String[] args){
	Food f=new Food();
	Thread t1=new Thread(f,"小明");//创建三个线程来共享一个同一个对象
	Thread t2=new Thread(f,"小红");
	Thread t3=new Thread(f,"小胖");
	}
}
class Food implements Runnable{
	private num=50;
	public void run(){
	for(int i=0;i<50;i++){
	if(num>0){   //使用Thread类名调用currentThread方法来获取对象,然后用对象调用getName方法获取姓名
	System.out.println(Thread.currentThread().getName()+"分了第"+num+"包零食");
	num--;
	}
	}
	}
}

3.线程的安全问题

当我们使用多线程并发访问同一个资源对象时,可能会出现线程不安全的问题,因为一个线程进入资源的同时其他线程也可以进入,这样就容易出问题.例如:我们使用Thread类中的sleep方法使线程休眠来模仿网络延迟,休眠时间越长问题就会越明显,当一个线程访问一个资源时进入休眠状态,其他线程这时也在访问这个资源,就会产生两个线程最后操作的结果相同问题;

解决方案

我们发现多个线程同时操作一个资源时会产生问题,所以有些操作在被一个线程访问时其他线程不能进入,当多线程进行抢占资源时,哪个线程最先进入资源就立刻锁住不让其他线程进入,这样就不会出现安全问题.

解决方式1:同步代码块

语法:synchronized(需要同步监听的对象){需要同步操作的代码}

此时同步锁就是()中的对象

解决方式2:同步方法

只要是使用synchronized修饰的方法都叫做同步方法

我们一般会把需要同步操作的代码都新建在一个方法中,使用synchronized修饰

谁调用同步方法谁就是同步锁;非static方法同步锁就是调用方法的对象,static方法同步锁就是当前方法所在类的字节码对象.

本文地址:https://blog.csdn.net/qq_44149884/article/details/107700027