面试运营相关线程

牛啊牛啊!这篇多线程技术笔记,阿里架构师看了都说好!

2021-03-16  本文已影响0人  前程有光

程序,进程,线程

Thread生命周期

Thread类中的常用方法

创建多线程的方式

继承Thread类

步骤:

class MThread extends Thread{
    private static int tickets = 100;
    @Override
    public void run() {
        while(true){
            if(tickets > 0){
                System.out.println(getName() + "卖票,票号为:" + tickets--);
            }else{
                break;
            }
        }
    }
}
public class ThreadTest {
    public static void main(String[] args) {
        MThread t1 = new MThread ();
        MThread t2 = new MThread ();
        MThread t3 = new MThread ();
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}

说明:局限于类的单继承性。

实现Runnable接口

步骤:

class MThread implements Runnable{
   private int tickets = 100;
   @Override
   public void run() {
       while(true){
           if(tickets > 0){
               System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + tickets--);
           }else{
               break;
           }
       }
   }
}
public class ThreadTest {
   public static void main(String[] args) {
       MThread m = new MThread();
       Thread t1 = new Thread(m);
       Thread t2 = new Thread(m);
       Thread t3 = new Thread(m);
       t1.setName("窗口1");
       t2.setName("窗口2");
       t3.setName("窗口3");
       t1.start();
       t2.start();
       t3.start();
   }
}

说明:不会局限于类的单继承性;适合处理多个线程共享数据的情况。

实现Callable接口

步骤:

class MThread implements Callable{
    @Override
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 2; i < 101; i+=2) {
                System.out.println(i);
                sum += i;
            }
        }
        return sum;
    }
}


public class ThreadTest {
    public static void main(String[] args) {
        MThread thread = new MThread ();
        FutureTask futureTask = new FutureTask(thread);
        new Thread(futureTask).start();
        try { 
            //get()返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值。
            Object sum = futureTask.get();
            System.out.println("总和为:" + sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}


说明:call()方法有返回值,并且可以抛出异常;callable支持泛型。

线程池

步骤:

class NumberThread implements Runnable{

    @Override
    public void run() {
        for(int i = 1;i < 101; i+=2){
             System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }
}

class NumberThread1 implements Runnable{

    @Override
    public void run() {
        for(int i = 2;i < 101; i+=2){
            System.out.println(Thread.currentThread().getName() + ": " + i);
        }
    }
}

public class ThreadPool {
    public static void main(String[] args) { 
        ExecutorService service = Executors.newFixedThreadPool(10);
        ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;
        service.execute(new NumberThread());//适用于Runnable
        service.execute(new NumberThread1());//适用于Runnable

        //service.submit(Callable callable);//使用于Callable
        service.shutdown();
    }
}


说明:提高了响应速度;降低资源消耗;便于线程管理。

线程同步机制

解决线程安全问题

同步代码块

synchronized(对象){//需要被同步的代码}
举例:三个窗口卖票

class Windows extends Thread{
    private static int tickets = 100;
    @Override
    public void run() {
        while(true){
            synchronized(Windows.class){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if(tickets > 0){
                    System.out.println(getName() + "卖票,票号为:" + tickets--);
                }else{
                    break;
                }
            }
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Windows t1 = new Windows();
        Windows t2 = new Windows();
        Windows t3 = new Windows();
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();
        t2.start();
        t3.start();
    }
}


同步方法

将synchronized放到方法的声明中。
举例:三个窗口卖票。

class Windows implements Runnable {
    private int tickets = 100;
    @Override
    public void run() {
        while(true){
            show();
        }
    }
    private synchronized void show(){
        if(tickets > 0){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + tickets--);
        }
    }

}
public class Test{
    public static void main(String[] args) {
        Windows t = new Windows();
        Thread t1 = new Thread(t);
        Thread t2 = new Thread(t);
        Thread t3 = new Thread(t);
        t1.setName("窗口1");
        t2.setName("窗口2");
        t3.setName("窗口3");
        t1.start();t2.start();t3.start();
    }
}


Lock

class A{
    private final ReentrantLock lock = new ReentrantLock();
    public void m(){
        lock.lock();
        try{
            //保证线程安全的代码
        }
        finally{
            lock.unlock();
        }
    }
}

举例:三个窗口卖票

class Window implements Runnable{
    private int ticket = 100;
    private ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while(true){
            try{
                lock.lock();
                if(ticket > 0){
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖票,票号为:" + ticket--);
                }
            }finally {
                lock.unlock();
            }
        }
    }
}
public class LockTest {
    public static void main(String[] args) {
        Window w = new Window();
        Thread t1 = new Thread(w);
        Thread t2 = new Thread(w);
        Thread t3 = new Thread(w);
        t1.setName("线程1");t2.setName("线程2");t3.setName("线程3");
        t1.start();t2.start();t3.start();
    }
}


synchronized和lock对比:

线程通信

三个方法

说明

举例:生产者消费者问题

class Clerk{
    private int productCount = 0;
    public synchronized void produceProduct(){
        if(productCount < 20){
            productCount ++;
            System.out.println(Thread.currentThread().getName() + "生产第" + productCount + "个产品");
            notify();
        }else {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public synchronized void consumeProduct() {
        if(productCount > 0){
            System.out.println(Thread.currentThread().getName() + "消费第" + productCount + "个产品");
            productCount --;
            notify();
        }else {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Productor extends Thread{
    private Clerk clerk;

    public Productor(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println("生产者" + Thread.currentThread().getName() + "开始生产");
        while(true){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            clerk.produceProduct();
        }
    }
}
class Consumer extends Thread{
    private Clerk clerk;

    public Consumer(Clerk clerk) {
        this.clerk = clerk;
    }

    @Override
    public void run() {
        System.out.println("消费者" + Thread.currentThread().getName() + "取走产品");
        while(true){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            clerk.consumeProduct();
        }
    }
}
public class ProductTest {
    public static void main(String[] args) {
        Clerk clerk = new Clerk();
        Productor p1 = new Productor(clerk);
        p1.setName("生产者1");
        Consumer c1 = new Consumer(clerk);
        c1.setName("消费者1");
        p1.start();c1.start();
    }
}


最后

在文章的最后作者为大家整理了很多资料!包括java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书等等!

全部免费分享给大家,欢迎关注公众号:前程有光领取!

上一篇 下一篇

猜你喜欢

热点阅读