Java线程知识总结(一)

时间:2022-01-19 11:50:10

线程:Thread
Thread thread = new Thread();
线程类里面代码如下:
@Override
public void run() {
if (target != null) {
target.run();
}
}
得知启动线程可以重写run方法,或者给target赋值,使用构造器调用init()赋值,即重写target(Runable)的run方法.

代码:

public static void main(String[] args) {
    // 第一个线程
    Thread thread = new Thread() {
        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            }
        }
    };
    thread.start();
    // 第二个线程
    Thread thread2 = new Thread(new Runnable() {
        @Override
        public void run() {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName());
            }

        }
    });
    thread2.start();

一个容易搞混的代码

    new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("Runnable中的run!");
        }
    }) {
        public void run() {
            System.out.println("Thread中的run!");
        }
    }.start();
    //结果是:Thread中的run!

定时器Timer

    System.out.println("主线程:"+Thread.currentThread().getName());
    new Timer().schedule(new TimerTask() {
        @Override
        public void run() {
            System.out.println("定时器中的线程:"+Thread.currentThread().getName());
            System.out.println("执行");
        }
    }, 10000[,1000]);
    for(int i=10;i>=0;) {
        System.out.println(i--);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    };

结果:主线程:main
10…1
定时器中的线程:Timer-0
执行
0

定时器迭代调用

    class MyTimerTask extends TimerTask {
        @Override
        public void run() {
            System.out.println("执行");
            new Timer().schedule(new MyTimerTask(), 1000);
        }
    }
    new Timer().schedule(new MyTimerTask(), 1000);

拓展:每天晚上三点收邮件(schedule可以写绝对时间)

线程安全

同步快

值得注意的是,可以用字符串常量来对不同的对象的方法加同步锁
public static void main(String[] args) {
    for (int i = 0; i < 1000; i++) {
        new SynchronizedTest().test();
    }
}

private void test() {
    Test1 test1 = new Test1();
    new Thread(new Runnable() {
        @Override
        public void run() {
            new Test1().show("111111111111");
        }
    }).start();
    new Thread(new Runnable() {
        @Override
        public void run() {
            new Test1().show("0000000000000");
        }
    }).start();
}

 class Test1 {
    public void show(String name) {
        synchronized("123") {
            int len = name.length();
            for (int i = 0; i < len; System.out.print(name.charAt(i++)));
            System.out.println();
        }
    }
}

线程的互斥与同步通信

方法中的synchronized是对this进行同步的
静态方法是对XXX.class进行同步的,也就是说对xxx.class加锁的对象也可以和xxx类的静态方法同步.
锁是放在资源内部的

一个经典题目

public class ThreadQuestion {
    //题目:主线程循环10次,子线程循环20次,然后主线程循环10次,再子线程...依次类推50次
    //思路:创建一个类来专门维护这个对象,首先定义两个互斥的方法(保证循环的过程中安全),
    //然后设置一个旗帜来决定顺序,进行wait和notify操作
    public static void main(String[] args) {
        //创建对象方便加锁
        QuestionService qs = new QuestionService();
        new Thread(new Runnable() {
            @Override
            public void run() {
                //子线程运行50次
                for(int i=0;i<50;i++) {
                    qs.sub();
                }
            }
        }).start();
        //主线程也是50次
        for(int i=0;i<50;i++) {
            qs.main();
        }
    }
}
class QuestionService{
    //旗帜
    private boolean shouldSub = false;
    public synchronized void main() {
        //如果不该主线程就等待
        //while防治伪唤醒
        while(shouldSub) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //执行循环
        for(int i=0;i<10;System.out.print(i++));
        System.out.println();
        //改变旗帜状态
        shouldSub = true;
        //打醒该类的wait的方法?
        this.notify();
    }
    public synchronized void sub() {
        //如果不该子线程就等待
        while(!shouldSub) {
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for(int i=0;i<20;System.out.print(i++));
        System.out.println();
        //改变状态
        shouldSub = false;
        //执行其他线程
        this.notify();
    }
}