用多线程来解决多人分零食问题
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
下一篇: 自己动手改造ADSL