java多线程相关学习笔记

优先级

先设置优先级在启动,不一定一定会优先级高先跑,只能说有效果

public class Testpriority {
    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
        MyPriority myPriority = new MyPriority();
        Thread t1 = new Thread(myPriority,"a");
        Thread t2 = new Thread(myPriority,"b");
        Thread t3 = new Thread(myPriority,"c");
        Thread t4 = new Thread(myPriority,"d");

        t1.start();

        t2.setPriority(1);
        t2.start();

        t3.setPriority(4);
        t3.start();
        t4.setPriority(Thread.MAX_PRIORITY);//最大为10
        t4.start();
    }
}


class MyPriority implements Runnable{
    public void run(){
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
    }
}

守护线程

daemon thread

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

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

虚拟机不用等待守护线程执行完毕 gc线程垃圾回收线程

package com.zihan.thread;

//测试守护线程
//上帝保佑你

public class DaemonThread{
    public static void main(String[] args) {
        God god = new God();
        You you = new You();
        Thread thread = new Thread(god);
        thread.setDaemon(true);//false 指用户线程,正常都是用户线程

        thread.start();//上帝守护线程启动

        new Thread(new You()).start();


    }


    }

class God implements Runnable{
    @Override
    public void run() {
        while(true){
            System.out.println("god bless you");
        }
    }
}



class You implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 36500; i++) {
            System.out.println("你好好活着吧");

        }
        System.out.println("=====good bye======");
    }
}


线程同步机制

一个资源多个程序同时用就有可能发生问题

解决方法即,让他们排队使用

线程同步其实就是一个等待机制

队列跟锁

每个对象都有一把锁,sleep不会释放锁

synchronized

锁会引起的问题:

一个线程持有锁会导致其他需要此锁的线程挂起;

性能倒置问题

TMD 想清楚什么叫他妈的多个线程操作同一对象

取钱不安全例子

public class kuangshen_unsafebank {
    public static void main(String[] args) {
        Account account = new Account("结婚基金",100);
        Bank2 you = new Bank2(account,50,"you");
        Bank2 wife = new Bank2(account,100,"wife");
        you.start();
        wife.start();
    }
}

class Account{
     String name;
     int balance;
     public Account(String name,int balance){
         this.name = name;
         this.balance = balance;
     }

}

class Bank2 extends Thread{
    Account account;
    int drawingmoney;
    int nowMoney;

    public Bank2(Account account,int drawingmoney,String name){
        super(name);//调用父类方法,即thread方法,来给thread命名。
        this.account = account;
        this.drawingmoney = drawingmoney;

    }

    @Override
    public void run() {
        if(account.balance<drawingmoney){
            System.out.println(Thread.currentThread().getName()+"钱不够,取不了");
            return;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        account.balance -= drawingmoney;
        nowMoney += drawingmoney;
        System.out.println(account.name+"余额为"+account.balance);
        //Thread.currentThread().getName() = this.getName(),因为继承了,thread.currentthread本身即为this
        System.out.println(this.getName()+"手里的钱是"+nowMoney);
    }
}

线程不安全例子

import java.util.ArrayList;

public class arraylistnotsafe {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                list.add(Thread.currentThread().getName());}).start();
        }
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(list.size());
    }
}

线程同步synchronized

1629648023(1)

会被修改的内容才上锁,只读一般不锁

常见不安全实例

  1. //一个多线程的不安全示范代码,本代码目标是从3个窗口购买总共一百张火车票
    public class SellTicket implements Runnable{
    
        public static void main(String[] args) {
            //以下代码是错误示范,因为只需构造一个SellTicket,实例化三个导致有3个100张票
            SellTicket window1 = new SellTicket();
            SellTicket window2 = new SellTicket();
            SellTicket window3 = new SellTicket();
    
            Thread t1 = new Thread(window1,"window1");
            Thread t2 = new Thread(window2,"window2");
            Thread t3 = new Thread(window3,"window3");
            t1.start();
            t2.start();
            t3.start();
        }
    
    
        private int ticket = 100;
    
        @Override
        public void run() {
            while(ticket>0) {
               ticket--;
                System.out.println("从窗口"+Thread.currentThread().getName()+"买了一张票,还剩"+ticket);
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
  2. 修改后的代码,但仍不安全,多线程同时修改变量,会出问题,添加sleep后问题变得更明显,相同票卖了多张,注释懒得改了,如果在ticket--前加sleep,甚至会多次出现负票等情况

    package com.zihan.thread_wangyi.Sell_Ticket;
    
    
    //一个多线程的不安全示范代码,本代码目标是从3个窗口购买总共一百张火车票
    public class SellTicket implements Runnable{
    
        public static void main(String[] args) {
            //以下代码是错误示范,因为只需构造一个SellTicket,实例化三个导致有3个100张票
            SellTicket window1 = new SellTicket();
    
    
            Thread t1 = new Thread(window1,"window1");
            Thread t2 = new Thread(window1,"window2");
            Thread t3 = new Thread(window1,"window3");
            t1.start();
            t2.start();
            t3.start();
        }
    
    
        private int ticket = 100;
    
        @Override
        public void run() {
            while(ticket>0) {
               ticket--;
                System.out.println("从窗口"+Thread.currentThread().getName()+"买了一张票,还剩"+ticket);
    //            try {
    //                Thread.sleep(100);
    //            } catch (InterruptedException e) {
    //                e.printStackTrace();
    //            }
            }
        }
    }
    
    

同步代码块

synchronized(对象){
    critical section;
}

解决问题

package com.zihan.thread_wangyi.Sell_Ticket;


//一个多线程的不安全示范代码,本代码目标是从3个窗口购买总共一百张火车票
public class SellTicket implements Runnable{

    public static void main(String[] args) {
        //以下代码是错误示范,因为只需构造一个SellTicket,实例化三个导致有3个100张票
        SellTicket window1 = new SellTicket();


        Thread t1 = new Thread(window1,"window1");
        Thread t2 = new Thread(window1,"window2");
        Thread t3 = new Thread(window1,"window3");
        t1.start();
        t2.start();
        t3.start();
    }


    private int ticket = 100;
    Object obj = new Object();

    @Override
    public void run() {
        synchronized (obj){
        while(ticket>0) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                ticket--;
                System.out.println("从窗口"+Thread.currentThread().getName()+"买了一张票,还剩"+ticket);
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

同步方法

同步方法锁的是this

带static锁的是.class反射会讲

package com.zihan.thread_wangyi.demo2;

public class Sellticket implements Runnable {

    public static void main(String[] args) {
        Sellticket sellticket= new Sellticket();
        Thread t1 = new Thread(sellticket,"window1");
        Thread t2 = new Thread(sellticket,"window2");
        t1.start();
        t2.start();
    }


    private int ticket = 100;

    @Override
    public void run() {
        while(true){
            if(Thread.currentThread().getName().equals("window1")){
                if(SynchronizedMethod()){
                    break;
                }

            }
            if(Thread.currentThread().getName().equals("window2")){
                synchronized (this){
                    if(ticket<=0){
                        break;
                    }
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    ticket--;
                    System.out.println("从窗口"+Thread.currentThread().getName()+"买了一张票,还剩"+ticket);

                }
            }
        }
    }

    private synchronized boolean SynchronizedMethod() {
        if(ticket<=0){
            return true;
        }
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        ticket--;
        System.out.println("从窗口"+Thread.currentThread().getName()+"买了一张票,还剩"+ticket);
        return false;
    }
}

lock锁

lock() 获得锁

unlock()释放锁

lock是接口,可以采用实现类Reentranlock来将其实例化

由于下方案例懒得重写,直接复制一开始错误案例,所以当一个线程进入后得到锁后会一直将所有票拿完然后解锁,最后只有一个窗口买了100张票,想要修改,我认为只需改成while(true),然后上锁,然后用if判断票是否卖完,卖完break,没卖完接着卖,然后再解锁。

用lock注意点是解锁要在finally块内,防止中断后,锁没解开。

package com.zihan.thread_wangyi.lock锁;


import java.util.concurrent.locks.ReentrantLock;

//一个多线程的不安全示范代码,本代码目标是从3个窗口购买总共一百张火车票
public class SellTicket implements Runnable{

    public static void main(String[] args) {
        //以下代码是错误示范,因为只需构造一个SellTicket,实例化三个导致有3个100张票
        SellTicket window1 = new SellTicket();


        Thread t1 = new Thread(window1,"window1");
        Thread t2 = new Thread(window1,"window2");
        Thread t3 = new Thread(window1,"window3");
        t1.start();
        t2.start();
        t3.start();
    }


    private int ticket = 100;
    ReentrantLock reentrantLock =new ReentrantLock();

    @Override
    public void run() {
        try{
            reentrantLock.lock();
        while(ticket>0) {
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                ticket--;
                System.out.println("从窗口"+Thread.currentThread().getName()+"买了一张票,还剩"+ticket);
                }
            }catch (Exception e) {
            e.printStackTrace();
        }finally {
            reentrantLock.unlock();
        }
    }
}
posted @ 2021-08-23 17:37  SaSikun  阅读(38)  评论(0)    收藏  举报