JAVA学习笔记16 线程

什么叫做单线程

栗子:
在这里插入图片描述如果这个页面设置不完成的话,就无法进入到记事本当中。这就是单线程,必须把一件事做完才能做另外一件事。

什么叫多线程

栗子:
在这里插入图片描述在扫雷中,一旦开始游戏,计时器就开始计时了,而不会等你走完下一步,游戏和时间是分别进行的,这就是多线程。

线程:是进程中的单个顺序控制流,是一条执行路径。

  • 单线程: -一个进程如果只有一条执行路径,则称为单线程程序。
  • 多线程: -个进程如果有多条执行路径,则称为多线程程序
    在这里插入图片描述
package Thread;

public class MyThreadDemo {
    public static void main(String[] args) {
        MyThread t1=new MyThread();
        MyThread t2=new MyThread();

//        t1.run();
//        t2.run();

        //void start () 导致此线程开始执行; Java虛拟机调用此线程的run方法
        t1.start();
        t2.start();
    }
}
package Thread;

public class MyThread extends Thread{
    @Override
    public void run() {
        for (int i=0;i<1000;i++){
            System.out.println(i);
        }
    }
}

执行结果:在这里插入图片描述从253开始第二个线程启动了。
在这里插入图片描述在这里插入图片描述

package Thread;

public class MyThreadDemo {
    public static void main(String[] args) {
        MyThread t1=new MyThread("飞机");
        MyThread t2=new MyThread("高铁");

//        t1.run();
//        t2.run();

        //void start () 导致此线程开始执行; Java虛拟机调用此线程的run方法
        t1.start();
        t2.start();

        System.out.println(Thread.currentThread().getName());
    }
}
public class MyThread extends Thread{
    public MyThread() {
    }

    public MyThread(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i=0;i<1000;i++){
            System.out.println(getName()+":"+i);
        }
    }
}

在这里插入图片描述

在这里插入图片描述测试使用sleep:

package Thread;

public class ThreadSleepDemo {
    public static void main(String[] args) {
        ThreadSleep ts1=new ThreadSleep("曹操");
        ThreadSleep ts2=new ThreadSleep("刘备");
        ThreadSleep ts3=new ThreadSleep("孙权");

        ts1.start();
        ts2.start();
        ts3.start();
    }
}
package Thread;

public class ThreadSleep extends Thread{
    public ThreadSleep() {
    }

    public ThreadSleep(String name) {
        super(name);
    }

    @Override
    public void run() {
        for (int i=0;i<1000;i++){
            System.out.println(getName()+":"+i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

执行结果:
在这里插入图片描述
每个线程,自己执行一次就sleep一秒,但是执行一次是特别快的,所以相当于每一秒每个只执行一次了,但是执行的顺序是按照抢占调度模式来的。

Join方法:等待这个线程死亡才会继续向下执行别的线程。

public class ThreadJoinDemo {
    public static void main(String[] args) {
        ThreadJoin ts1=new ThreadJoin("康熙");
        ThreadJoin ts2=new ThreadJoin("四阿哥");
        ThreadJoin ts3=new ThreadJoin("八阿哥");

        ts1.start();
        try {
            ts1.join();//等待康熙执行完毕之后,之后两个线程才执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        ts2.start();
        ts3.start();
    }
}

Daemon方法:设置某一个线程为守护线程,也就是非主要线程,当主线程内容执行完成之后,如果只剩下守护线程,则Java虚拟机退出,不在继续执行。

package Thread;

public class ThreadDaemonDemo {
    public static void main(String[] args) {
        MyThread ts1=new MyThread("关羽");
        MyThread ts2=new MyThread("张飞");

        Thread.currentThread().setName("刘备");

        ts1.setDaemon(true);
        ts2.setDaemon(true);
        ts1.start();
        ts2.start();

        for (int i=0;i<10;i++){
            System.out.println( Thread.currentThread().getName()+":"+i);
        }
    }

}

在这里插入图片描述
在这里插入图片描述

package Thread;

public class MyRunnable implements Runnable {
    @Override
    public void run() {
        for (int i =0;i<1000;i++){
            System.out.println(Thread.currentThread().getName()+i);
        }
    }
}
public class MyRunnableDemo {
    public static void main(String[] args) {
        MyRunnable mr=new MyRunnable();

        Thread t1=new Thread(mr);
        Thread t2=new Thread(mr);

        t1.start();
        t2.start();
    }
}

相比继承Thread类,实现Runnable接口的好处

  • 避免了Java单继承的局限性(因为使用Runnable实现类,可以再去继承别的类了)

  • 适合多个相同程序的代码去处理同一个资源的情况,把线程和程序的代码、数据有效分离,较好的体现了面向对象的设计思想。(因为这样只使用了Thread其中一个接口的功能,比起直接继承,耦合度更低了)
    在这里插入图片描述在这里插入图片描述
    多线程的实质依然是一个cpu进行分时处理多个进程,只是从宏观上来看好像是同时进行的,实际微观上是分步进行的。

    在这里插入图片描述在这里插入图片描述

在这里插入图片描述

package Thread;

public class SellTicket implements Runnable{
    private int tickets=100000000;
    private Object lock =new Object();//使用同一把锁来锁起来
    @Override
    public void run() {
            while (true) {
                //同步锁
                synchronized (lock) {
                    if (tickets > 0) {
                        //sleep 100ms
                        try {
                            Thread.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //卖票
                        System.out.println(Thread.currentThread().getName() + "正在售出第" + tickets + "张票");
                        tickets--;
                    }
            }
        }
    }
}

package Thread;

public class SellTicketDemo {
    public static void main(String[] args) {
        SellTicket st=new SellTicket();

        Thread t1=new Thread(st,"窗口1");
        Thread t2=new Thread(st,"窗口2");
        Thread t3=new Thread(st,"窗口3");

        t1.start();
        t2.start();
        t3.start();
    }
}

执行结果:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

package Thread;

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

public class SellTicket implements Runnable {
    private static int tickets = 1000;
    private Object lock = new Object();//使用同一把锁来锁起来
    private int x = 0;
    private Lock lockk = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            try {
                lockk.lock();
                if (x % 2 == 0) {
                    //同步锁
                    if (tickets > 0) {
                        //sleep 100ms
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        //卖票
                        System.out.println(Thread.currentThread().getName() + "正在售出第" + tickets + "张票");
                        tickets--;
                    }
                }
            } finally {
                lockk.unlock();
            }
            x++;
        }
    }
}

为了防止出现异常而导致unlock没有执行,也就是只上锁而没有释放锁的情况,使用try,finally

生产者消费者模式

在这里插入图片描述需要注意:使用wait和notify这种等待唤醒操作,必须使用synchronized修饰
如:

public synchronized void put(int milk){//使用wait和notify这种等待唤醒操作,必须使用synchronized修饰
        //如果有牛奶,等待消费了之后才能继续往box里面放牛奶
        if (state){
            try {
                wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        //如果没有牛奶,就生产牛奶
        this.milk=milk;
        System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱中");
        //生产完毕后,修改奶箱状态
        state=true;

        notifyAll();
    }

在这里插入图片描述Box:

package Thread;
public class Box {
    private int milk;
    private boolean state=false;

    public synchronized void put(int milk){//使用wait和notify这种等待唤醒操作,必须使用synchronized修饰
        //如果有牛奶,等待消费了之后才能继续往box里面放牛奶
        if (state){
            try {
                wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        //如果没有牛奶,就生产牛奶
        this.milk=milk;
        System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱中");
        //生产完毕后,修改奶箱状态
        state=true;

        notifyAll();
    }

    public synchronized void get(){
        //如果没有牛奶,等待生产好了,box里面有牛奶了才能取牛奶
        if(!state){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("用户拿到第"+this.milk+"瓶奶");
        state=false;

        //唤醒其他等待进程
        notifyAll();
    }
}

Customer:

package Thread;

public class Customer implements Runnable{
    private Box b;
    public Customer(Box b) {
        this.b=b;
    }

    @Override
    public void run() {
        while (true){
            b.get();
        }
    }
}

Producer:

package Thread;

public class Producer implements Runnable{
    private  Box b;
    public Producer(Box b) {
        this.b=b;
    }

    @Override
    public void run() {
        for (int i=1;i<=5;i++){
            b.put(i);
        }
    }
}

主程序:

package Thread;

public class BoxDemo {
    public static void main(String[] args) {
        Box b=new Box();

        Producer p=new Producer(b);

        Customer c=new Customer(b);

        //创建生产者线程与消费者线程
        Thread tp=new Thread(p);
        Thread tc=new Thread(c);

        tp.start();
        tc.start();
    }
}

执行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值