Java笔记3(线程)

只是一些自己认为重点和易错点的笔记

线程相关笔记

1、进程与线程

  • 进程由静态的程序运行是产生的;
  • 进程相当于是一个大的模块,里边包含了各个线程来具体实现东西;
  • 至少有一个线程,否则进程没有意义;
  • 线程开启不一定立即执行,是由CPU调度的。

2、创建线程的方法

a、通过继承Thread类来创建

  • 创建类来继承Thread类(假设类为test);
  • 重写run()方法;
  • 创建test类的对象,用这个对象调用start()方法来启动线程

b、通过实现Runnable接口来创建

  • 创建类来继承Thread类(假设类为test1);

  • 重写run()方法;

  • 创建test1类的对象p,再创建Thread对象,将p放到Thread对象中,在调用start方法

    即用线程的对象类开启线程(要用魔法打败魔法*_*)

    //第二种方法的第三步   new Thread(p).start();
    

    两种方法的前两步都是一样的,只有第三步有些差别

3、并发

  • 一个资源可以被多个线程所使用;
  • 但是会有问题,例如:多人抢票,会出现多个人抢到同一张票的情况;

4、静态代理模式

//结婚代理
//真实对象和代理对象要实现同一个接口
//真实对象专注做自己的事
public class StaticProxy {
    public static void main(String[] args) {
        MarryCompany mc = new MarryCompany(new You());
        mc.marry();
    }
}

//结婚接口
interface Marry{
    void marry();
}

//你
class You implements Marry{
    @Override
    public void marry() {
        System.out.println("Today marry.");
    }
}

//婚庆公司
class MarryCompany implements Marry{
    private Marry target;
    public MarryCompany(Marry tar){
        this.target=tar;
    }
    @Override
    public void marry() {
        this.befor();
        this.target.marry();
        this.after();
    }

    private void after() {
        System.out.println("后");
    }

    private void befor() {
        System.out.println("前");
    }
  • 使用lamda表达式来简化掉真实对象

    /结婚代理
    public class StaticProxy {
        public static void main(String[] args) {
    //        MarryCompany mc = new MarryCompany(new You());
    //        mc.marry();
    
    //使用lamda表达式可以简化掉真实对象部分的实现
            new MarryCompany(()-> System.out.println("today.....")).marry();
        }
    }
    
    //结婚接口
    interface Marry{
        void marry();
    }
    
    
    //你
    //class You implements Marry{
    //
    //    @Override
    //    public void marry() {
    //        System.out.println("Today marry.");
    //    }
    //}
    
    //婚庆公司
    class MarryCompany implements Marry{
        private Marry target;
        public MarryCompany(Marry tar){
            this.target=tar;
        }
        @Override
        public void marry() {
            this.befor();
            this.target.marry();
            this.after();
        }
    
        private void after() {
            System.out.println("后");
        }
    
        private void befor() {
            System.out.println("前");
        }
    }
    

5、线程停止(stop)

  • 线程五大状态
    • 创建
    • 就绪
    • 运行
    • 阻塞
    • 死亡
public class TestStop implements Runnable {
//设置标志位
    boolean flag = true;

    @Override
    public void run() {
        int i = 0;
        while (flag){
            System.out.println("线程运行中"+ i++);
        }
    }
//改变标志位状态
    public void stop(){
        this.flag = false;
    }

    public static void main(String[] args) {
        TestStop tt = new TestStop();
//开启线程
        new Thread(tt).start();
//运行主线程
        for (int i = 0; i < 1000; i++) {
            System.out.println(i);
            if(i == 990){
                tt.stop();
                System.out.println("线程停止了");
            }
        }
    }
}

6、线程休眠(sleep)

  • 可实现倒计时
  • 模拟网络延时
  • 每个对象都有一把锁,sleep不会释放锁。
//当前时间的显示
public static void main(String[] args) {
        Date date = new Date(System.currentTimeMillis());
        while (true){

            try {
                System.out.println(new SimpleDateFormat("HH:mm:ss").format(date));
                Thread.sleep(1000);
                date = new Date(System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


    }

7、线程礼让(yield)

/**
 * 测试线程礼让
 */
public class TestYield {
    public static void main(String[] args) {
        Myyeird my = new Myyeird();
        new Thread(my,"a").start();
        new Thread(my,"b").start();
    }
}

class Myyeird implements Runnable{

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程开始");
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + "线程结束");
    }
}


//这个没测试成功,不知道什么地方出了问题

8、线程强制执行(join)

  • 在达到条件之前CPU随机调度线程

    当达到条件后先调用插队的线程。

public class TestJoin implements Runnable {
    @Override
    public void run() {
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (int i = 0; i < 1000; i++) {
            System.out.println("插队的来了" + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        //启动线程
        TestJoin tj = new TestJoin();
        Thread thread = new Thread(tj);
        thread.start();
		//主线程
        for (int i = 0; i < 500; i++) {
            if(i==200){
                thread.join();
            }
            System.out.println("main" + i);
        }
    }
}

9、观测线程状态

public class TestState {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
            for (int i = 0; i < 2; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("延迟结束");
        });
        //监测状态
        Thread.State state = thread.getState();
        System.out.println(state);    //New

        //开启线程
        thread.start();
        state = thread.getState();
        System.out.println(state); //run

        while (state != Thread.State.TERMINATED){  //主要线程不终止,就一直输出状态
            Thread.sleep(100);
            state = thread.getState();   //更新线程状态
            System.out.println(state);
        }


    }
}
NEW
RUNNABLE
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
延迟结束
TERMINATED

10、线程优先级

  • 优先级高只是被CPU调度的几率高
public class TestPriority {
    public static void main(String[] args) {
        //主线程默认优先级
        System.out.println(Thread.currentThread().getName() + "---->"+Thread.currentThread().getPriority());

        MyPriority mp = new MyPriority();
        Thread t1 = new Thread(mp);
        Thread t2 = new Thread(mp);
        Thread t3 = new Thread(mp);
        Thread t4 = new Thread(mp);
        
        t1.setPriority(Thread.MIN_PRIORITY);  //优先级最小为1
        t1.start();
        t2.setPriority(4);
        t2.start();
        t3.setPriority(8);
        t3.start();
        t4.setPriority(Thread.MAX_PRIORITY);  //优先级最大为10
        t4.start();
    }
}

class MyPriority implements Runnable{

    @Override
    public void run() {
        //输出线程名称和优先级
        System.out.println(Thread.currentThread().getName() + "---->"+ Thread.currentThread().getPriority());
    }
}
main---->5
Thread-0---->1
Thread-1---->4
Thread-3---->10
Thread-2---->8

11、守护线程

  • 线程分为用户线程守护线程

  • 虚拟机必须确保用户线程执行完毕;

    不用等待守护线程执行完毕。

public class TestDeamon {
    public static void main(String[] args) {
        God god = new God();
        You you = new You();

        Thread thread = new Thread(god);
        thread.setDaemon(true);         //创建的线程默认为用户线程
        thread.start();

        new Thread(you).start();
    }
}

class God implements Runnable{

    @Override
    public void run() {
        while(true){
            System.out.println("上帝守护着你");
        }
    }
}

class You implements Runnable{

    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("一直开心地活着");
        }
        System.out.println("goodbye,world");
    }
}

12、同步方法和同步块

  • 同步方法:添加synchronized修饰符

    同步块:

    public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            for (int i = 0; i < 10000; i++) {
                new Thread(()->{
    
                    //锁的对象是需要增删改的
                    synchronized(list){
                        list.add(Thread.currentThread().getName());
                    }
                }).start();
            }
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(list.size());
        }
    

13、Lock锁

public class BuyTicket {
    //购票
    public static void main(String[] args) {
        Buy buy = new Buy();

        new Thread(buy).start();
        new Thread(buy).start();
        new Thread(buy).start();
    }
}

class Buy implements Runnable{
    //票数
    int tackets = 10;

    ReentrantLock lock = new ReentrantLock();
    @Override
    public void run() {
        while (true){
            try{
                lock.lock();   //加锁
                if(tackets > 0){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                    }
                    System.out.println("票数为:" + tackets--);
                }else {
                    break;
                }
            }finally {
                lock.unlock();  //解锁
            }
        }

    }
}

非常感谢狂神的教学

有错误的地方欢迎指正,一起交流

posted @ 2021-02-19 20:10  一个菜菜的boy  阅读(36)  评论(0)    收藏  举报