传统多线程相关技术

一、多线程的实现方式

1、继承Thread类
Thread t2 = new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                while(true){
                    System.out.println(Thread.currentThread().getName());
                }
            }
        };
t2.start();
2、实现Runnable接口
new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                while(true){
                    System.out.println(Thread.currentThread().getName());
                }
            }
        }).start();

使用Lambda表达式重写
new Thread(()->{//用lambda表达式代替
            while(true){
                System.out.println(Thread.currentThread().getName());
            }
        }).start(); 
  • 注意:多线程机制不会提高程序的运行效率,之所以用多线程下载,是为了抢服务器的带宽
3、面试题
//面试题:会实现Thread里面的方法还是Runnable里面的方法?   
new Thread(new Runnable() {
    @Override
    public void run() {
        while(true){
         System.out.println("Runnable "+Thread.currentThread().getName());
       }
   }
}){
   @Override
   public void run() {
       while(true){
           System.out.println("Thread "+Thread.currentThread().getName());
       }
   }
}.start();

//会先在子类中找方法,若子类没有,在输出参数任务中的runnable run,若都没有,则执行Thread类中默认的run()方法。
4、练习:

需求:设计4个线程,其中两个线程每次对j增加1,另外两个线程对j每次减少1
思路:将两个runnable作为内部类,要共享的数据作为外部类的成员变量

public class MultiThreadShareData {

    private int j;
    public static void main(String[] args) {
        MultiThreadShareData mt = new MultiThreadShareData();
        for(int i = 0;i<2;i++){
            new Thread(mt.new Inc()).start();
            new Thread(mt.new Dec()).start();
        }

    }
    //两个方法为同一个锁对象,this
    private synchronized void inc(){
        j++;
        System.out.println(Thread.currentThread().getName()+" inc " +j);
    }

    private synchronized void dec(){
        j--;
        System.out.println(Thread.currentThread().getName()+" dec " +j);
    }

    class Inc implements Runnable{
        @Override
        public void run() {
            for(int i = 0;i<100;i++){
                inc();
            }

        }
    }

    class Dec implements Runnable{
        @Override
        public void run() {
            for(int i = 0;i<100;i++){
                dec();
            }
        }
    }
}
5、实现Runnable接口比继承Thread类所具有的优势:

1.适合多个相同的程序代码的线程去共享同一个资源。
2. 可以避免java中的单继承的局限性。
3. 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和数据独立。
4. 线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
5.实现Runnable接口,更能体现面向对象的概念,执行体放在Runnable的实现类中

二、线程同步通信技术

需求:主线程执行100次,子线程执行10次,交替执行,共循环50次

public class TranditionCommunication {

    public static void main(String[] args) {
        //或直接将内部类改为静态内部类则可以直接创建内部类的实例对象
        final Business business = new TranditionCommunication().new Business();

        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i = 0;i<50;i++){
                    business.sub(i);
                }
            }
        }).start();

        for(int i = 0;i<50;i++){
            business.main(i);
        }
    }

    //内部类
   class Business{

        boolean isSub = true;
        public synchronized void sub(int i){
            while(!isSub){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for(int j=0;j<10;j++){
                System.out.println("sub method "+j+" loop of "+i);
            }

            isSub = false;
            this.notify();
        }

        public synchronized void main(int i){
            while(isSub){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for(int j=0;j<100;j++){
                System.out.println("main method "+j+" loop of "+i);
            }
            isSub = true;
            this.notify();
        }
    }
}
  • this.notify与 this.wait()需要与synchronized的锁对象一致,synchronized写在方法上则也是用this实现互斥

三、定时器

需求:第一次在2s后发生,第二次在4s,后面又是2s,交替进行

public class TranditionalTimerTest {

    static int count = 0;

    public static void main(String[] args) {

        class MyTimerTask extends TimerTask{

            @Override
            public void run() {
                count ++;
                count = count % 2;

                System.out.println("bombing!");
                new Timer().schedule(new MyTimerTask(),2000+2000*count);
            }
        }

        new Timer().schedule(new MyTimerTask(),2000);
//        new Timer().schedule(new TimerTask() {
//            @Override
//            public void run() {
//                System.out.println("bombing!");
//            }
//        },5000,3000);//第一次在5s后发生,后面每隔3次发生一次
//
        while(true){
            System.out.println(new Date().getSeconds());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

你可能感兴趣的:(JAVA基础)