多线程-Thread类、Runnable接口、线程池、线程安全与同步

为了实现多部分代码同时执行;

Thread类:1.继承Thread类:定义一个类继承Thread,重写run方法,创建子类对象,调用start方法,开启线程

      2.实现Runnable接口:避免了单继承的局限性,

//分别用两条线程同时计算1-100的和,1-200的和
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //获取线程池对象
        ExecutorService es=Executors.newFixedThreadPool(2);
        //创建线程任务对象
        MySum m1=new MySum(100);
        MySum m2=new MySum(200);
        //提交线程任务
        Future<Integer> f1=es.submit(m1);
        Future<Integer> f2=es.submit(m2);
        //获取返回值
        System.out.println(f1.get());
        System.out.println(f2.get());
        //销毁线程池
        es.shutdown();
    }
public class MySum implements Callable<Integer> {
    private int n;
    public MySum(){}
    public MySum(int n){
        this.n=n;
    }
    
    public Integer call() throws Exception {
        int sum=0;
        for(int i=1;i<=n;i++){
            sum+=i;
        }
        return sum;
    }
    
}

 

匿名内部类:1.创建线程对象时,直接重写Thread类中的run方法

      2.使用匿名内部类的方式实现Runnable接口,重新Runnable接口中的run方法

线程池:1.Runnable接口:①创建线程池 ②创建线程任务对象  ③提交线程任务  ④ 获取返回值 ⑤ 销毁线程池

    2.Callable接口:

有返回值用Runnable,

例题:

public class MySum implements Callable<Integer> {
    private int n;
    private int m;
    public MySum(){}
    public MySum(int n,int m){
        this.m=m;
        this.n=n;
    }
    public Integer call() throws Exception {
        int num1=0;
        int num2=0;
        int sum=0;
        int Sum=0;
        for(int i=1;i<n;i++){
            num1=sum+=i;
        }
        for(int i=1;i<m;i++){
            num2=sum+=i;
        }
        Sum=num1+num2;
        return Sum;
    }
    
}

测试类代码

public static void main(String[] args) throws InterruptedException, ExecutionException {
        //获取线程池对象
        ExecutorService es=Executors.newFixedThreadPool(2);
        //创建线程任务对象
        MySum m1=new MySum(20,50);
        MySum m2=new MySum(60,300);
        //提交线程任务
        Future<Integer> f1=es.submit(m1);
        Future<Integer> f2=es.submit(m2);
        //获取返回值
        System.out.println(f1.get());
        System.out.println(f2.get());
        System.out.println(f1.get()+f2.get());
        //销毁线程池
        es.shutdown();
    }

 

线程安全案例:电影院卖票

public class Ticket implements Runnable {
    private int ticket=100;
    public void run() {
        while(true){
            if(ticket>0){
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"卖出了第"+ticket--+"张票");
                
            }
        }
    }
}
public class Demo01 {
    public static void main(String[] args) {
        //创建线程任务
        Ticket r=new Ticket();
        //创建线程对象
        Thread t1=new Thread(r);
        Thread t2=new Thread(r);
        Thread t3=new Thread(r);
        //开启线程
        t1.start();
        t2.start();
        t3.start();
    }
}

 

线程安全问题处理:1.同步代码块:在代码块声明上 加上synchronized

            同步代码块中的锁对象可以是任意的对象;但多个线程时,要使用同一个锁对象才能够保证线程安全

         2.同步方法:在方法声明上加上synchronized

            同步方法中的锁对象是 this

 

posted @ 2021-07-26 16:13  XY12313  阅读(61)  评论(0)    收藏  举报