java 从入门到精通

java 中Thread

2021-05-11  本文已影响0人  Exception_Cui

首先了解下线程的状态


微信图片_20210513144401.png

继承方式实现

package ThreadTest;

/**
 * Created by kumamon on 2021/5/13.
 */
public class ThreadDemo {
    public static void main(String[] args) {
        MythreadDemo mythreadDemo = new MythreadDemo();
        mythreadDemo.start();
    }

}
class MythreadDemo extends Thread{
    @Override
    public void run() {
        System.out.println("使用 extends Thread 来创建线程");
    }
}

Ruannable方式(推荐使用,因为java是单继承,这种方式还可以有父类)

package ThreadTest;

/**
 *  Runnable
 * 直接使用 extends  Thread 的方式 不能实现多继承
 * 使用这种方式可以继续继承其他的类
 * 解耦
 *
 * Created by kumamon on 2021/5/12.
 */
public class Runnable {
    public static  void main(String[] args) {
        Thread thread=new Thread(new MyRunnableMain());
        thread.start();
    }


}
class MyRunnableMain implements java.lang.Runnable {

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println(Thread.currentThread().getName()+ i);
        }
    }
}

线程守护

package ThreadTest;

/**
 * 守护线程
 * 一个线程设置为守护线程后,当被守护的线程退出了,那么自己的线程也就退出
 *
 * main里面只能创建一个唯一的线程,要么守护线程不起效
 * Created by kumamon on 2021/5/13.
 */
public class Thread_Deamon {
    public static void main(String[] args) throws InterruptedException {
        T1 t1 = new T1();
        t1.setDaemon(true); //T1 设置为main的守护线程 ,当main线程结束后,T1也跟着结束
        t1.start();

        //T2 t2 = new T2();
        //t2.start();  // T2没有设置,main 线程结束后,T2还在执行,等T2结束后,进程停止

        for (int i = 0; i < 5; i++) {
            Thread.sleep(1000);
            System.out.println("主线程   正在执行");
        }
        System.out.println("主线程执行完毕,退出");
    }

}



class T1 extends Thread {
    @Override
    public void run() {
        for (;;) {  //死循环
            try {

                Thread.sleep(1000);
                System.out.println("子线程 1");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


class T2 extends Thread {
    @Override
    public void run() {
        for (;;) {  //死循环
            try {

                Thread.sleep(1000);
                System.out.println("子线程 2");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

线程加入和让出

package ThreadTest;

/**
 * Created by kumamon on 2021/5/13.
 */
public class Thread_Join_Yield {
    public static void main(String[] args) {
        Thread thread=new T();
        thread.start();

        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName()+"正在吃"+i+"包子");
                if(i==5){
                    /**
                     * 线程加入。
                     * 主线程在执行过程中, 让 子线程先执行
                     *

                     @System.out.println("子线程加入先吃包子");
                     @thread.join(); 

                     * */

                    /**
                     * 线程礼让。(是执行自己礼让)
                     * 主线程在执行过程中, 让子线程先执行
                     * 这种方式不一定成功,取决于电脑的CPU调度
                     @System.out.println("自己礼让,让子线程先吃");
                     @Thread.yield();
                     * */

                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class T extends  Thread{
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            try {
                Thread.sleep(1000);
                System.out.println(this.getName()+"正在吃"+i+"包子");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

不同步的线程(数据不合理)

package ThreadTest;

/**
 * 窗口同时在卖一张票, 还卖了不存的票,(数据不合理)
 * 相当于 3个人在同一时间上同一个厕所
 * <p>
 * Created by kumamon on 2021/5/12.
 */
public class Thread_No_Synchronized {
    public static void main(String[] args) {
        MyRunnable1 myRunnable = new MyRunnable1();

        Thread thread1 = new Thread(myRunnable, "窗口1");
        Thread thread2 = new Thread(myRunnable, "窗口2");
        Thread thread3 = new Thread(myRunnable, "窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }


}

class MyRunnable1 implements java.lang.Runnable {
    int sum = 100;

    @Override
    public void run() {
        while (true) {
            if (sum > 0) {  //判断票数还有多少张呢
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
                sum--;
            }
        }
    }
}

同步代码块(数据合理) 还是上面的例子,不会出现-1 张票

package ThreadTest;

/**
 * 使用 Synchronized  前提是多个线程 访问同一个数据 (线程安全)
 * 相当于 3个人在同一时间上同一个厕所
 * 但是只能一个一个来,一个上完另一个在上
 * <p>
 *
 *
 *  原理就是 jvm在运行时会检测这个锁的对象属于那个线程
 *  这样争抢的过程中,只能有锁对象的执行
 *
 *
 * Synchronized 包含的是 访问同一数据的代码
 *
 * Created by kumamon on 2021/5/12.
 */
public class Thread_Synchronized_Object {

    public static void main(String[] args) {
        MyRunnable4 myRunnable = new MyRunnable4();

        Thread thread1 = new Thread(myRunnable, "窗口1");
        Thread thread2 = new Thread(myRunnable, "窗口2");
        Thread thread3 = new Thread(myRunnable, "窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }



}

class MyRunnable4 implements java.lang.Runnable {
    int sum = 100;  //票数
    Object obj = new Object();  //设置锁 对象为Object 可以为任意的
    @Override
    public void run() {
        synchronized (obj) {
            while (sum > 0) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
                sum--;
            }
        }
    }

}

同步方法(数据安全)

package ThreadTest;

/**
 * 使用同步方法(数据安全)
 * 和

 * 相当于 3个人在同一时间上同一个厕所
 * 但是只能一个一个来,一个上完另一个在上
 * <p>
 * Created by kumamon on 2021/5/12.
 */
public class Thread_Synchronized_Method {
    public static void main(String[] args) {
        MyRunnable2 myRunnable = new MyRunnable2();

        Thread thread1 = new Thread(myRunnable, "窗口1");
        Thread thread2 = new Thread(myRunnable, "窗口2");
        Thread thread3 = new Thread(myRunnable, "窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }




}
class MyRunnable2 implements java.lang.Runnable {
    int sum = 100;  //票数

    Object obj = new Object();  //设置锁 对象为Object 可以为任意的

    @Override
    public void run() {
        pay();

        /**
         * 等同于如下代码  不过obj 是 MyRunnable  而已就是this
        synchronized (obj) {
         while (sum > 0) {

         try {
         Thread.sleep(10);
         } catch (InterruptedException e) {
         e.printStackTrace();
         }
         System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
         sum--;
         }
         }
         */

    }

    private synchronized void pay(){
        while (sum > 0) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
            sum--;
        }
    }


}

静态同步方法

package ThreadTest;

/**
 * 使用 Synchronized  前提是多个线程 访问同一个数据 (线程安全)
 * 相当于 3个人在同一时间上同一个厕所
 * 但是只能一个一个来,一个上完另一个在上
 *
 * 这种一般来保证 单例模式  的线程安全
 *
 *
 * <p>
 * Created by kumamon on 2021/5/12.
 */
public class Thread_Synchronized_Method_Static {

    public static void main(String[] args) {
        MyRunnable3 myRunnable = new MyRunnable3();

        Thread thread1 = new Thread(myRunnable, "窗口1");
        Thread thread2 = new Thread(myRunnable, "窗口2");
        Thread thread3 = new Thread(myRunnable, "窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }



}
class MyRunnable3 implements java.lang.Runnable {
    static int sum = 100;  //票数
    @Override
    public void run() {
        payStatic();
    }

    private static synchronized void payStatic(){  //此处的锁是 MyRunnable3 .class  不是this对象
        while (sum > 0) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
            sum--;
        }
    }

}

Lock锁同步

package ThreadTest;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 使用 Lock  前提是多个线程 访问同一个数据 (线程安全)
 * 相当于 3个人在同一时间上同一个厕所
 * 但是只能一个一个来,一个上完另一个在上
 * <p>
 * <p>
 *
 * 使用方式
 *
 *  创建Lock 对象
 *  Lock lock = new ReentrantLock();
 *
 *  在访问共享数据前
 *
 *  lock.lock();
 *  ***
 *  *访问共享数据代码
 *  ***
 *  lock.unlock();
 *
 *  建议增加try 这样无论这次操作是否有异常 都会释放,让下一个线程访问
 *
 * Created by kumamon on 2021/5/12.
 *
 *
 */
public class Thread_Lock {

    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();

        Thread thread1 = new Thread(myRunnable, "窗口1");
        Thread thread2 = new Thread(myRunnable, "窗口2");
        Thread thread3 = new Thread(myRunnable, "窗口3");
        thread1.start();
        thread2.start();
        thread3.start();
    }



}
class MyRunnable implements java.lang.Runnable {
    int sum = 100;  //票数

    Lock lock = new ReentrantLock();


    @Override
    public void run() {
        lock.lock();
        try {
            while (sum > 0) {

                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "正在卖" + sum + "张票");
                sum--;
            }
        } finally {
            lock.unlock();
        }
    }
}

线程死锁

package ThreadTest;

/**
 *
 * 线程死锁是指两个或两个以上的线程互相持有对方所需要的资源,
 * 由于synchronized的特性,一个线程持有一个资源,或者说获得一个锁,
 * 在该线程释放这个锁之前,其它线程是获取不到这个锁的,
 * 而且会一直死等下去,因此这便造成了死锁。
 *
 *
 * Created by kumamon on 2021/5/13.
 */
public class ThreadDead {
    public static void main(String[] args) {
        MyThreadDead threadA = new MyThreadDead(true);
        MyThreadDead threadB = new MyThreadDead(false);

        threadA.start();
        threadB.start();
    }
}

class MyThreadDead extends Thread{

    boolean flag=true;
    public static Object o1= new Object();

    public static Object o2 =new Object();

    public MyThreadDead(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if(flag){
            synchronized (o1){
                System.out.println("A线程持有了 o1的对象锁,未执行完 不释放 o1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (o2){
                    System.out.println("A线程");
                }

            }
        }else{
            synchronized (o2){
                System.out.println("B线程持有了 o2的对象锁,未执行完 不释放 02");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (o1){
                    System.out.println("B线程");
                }

            }
        }


    }
}

线程通讯

package ThreadTest;

/**
 * Created by kumamon on 2021/6/3.
 * <p>
 * 模拟
 * 观众看电视
 * 演员录电视
 */
public class Thread_TongXun {

    public static void main(String[] args) {
        TV tv = new TV();
        new Yanyuan(tv).start();
        new Guanzhong(tv).start();
    }
}

class Yanyuan extends Thread {
    TV tv;

    public Yanyuan(TV tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            tv.yan();
        }

    }
}

class Guanzhong extends Thread {
    TV tv;

    public Guanzhong(TV tv) {
        this.tv = tv;
    }


    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            tv.kan();
        }

    }
}


class TV {

 
    boolean flag = false;  //设置标志位,什么时候演员录  什么时候观众看

    public synchronized void yan() {

        //等待观众看完的通知
        if (flag) {  //演员录
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("演员录完电视,通知观众看电视");
        this.flag = !this.flag;
        this.notifyAll();//通知观众



    }

    public synchronized void kan() {
        if (!flag) {   //观众看
            //等待 演员录完电视的通知
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("观众看完了电视-----通知演员继续录");
         this.flag = !this.flag;
        this.notifyAll();
     


    }

}

image.png
上一篇下一篇

猜你喜欢

热点阅读