当前位置: 移动技术网 > IT编程>开发语言>Java > 用多线程来解决多人分零食问题

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

2020年07月31日  | 移动技术网IT编程  | 我要评论
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

如您对本文有疑问或者有任何想说的,请 点击进行留言回复,万千网友为您解惑!

相关文章:

验证码:
移动技术网