继承Thread类、实现Runnable接口、实现Callable接口

目录

1.线程

1.1继承Thread类

1.2实现Runnable接口

1.3实现Callable接口

2.线程方法

2.1join线程

2.2后台线程-Daemon线程

2.3.权重 Priority

2.4.wait

2.5.Notify

3.例子

3.1.卖票-超卖-使用

3.2生产者和消费者

商品

生产者

消费者

测试



 

1.线程

 

1.1继承Thread类

 

package com.yg.thread;

/**
 * 不推荐使用,
 * 由于单继承的原因
 */
public class ThreadDemo extends Thread {

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "--子线程");
        }
    }

    public static void main(String[] args) {
        ThreadDemo thread1 = new ThreadDemo();
        thread1.start();
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "--主线程");
        }
    }

}

1.2实现Runnable接口

package com.yg.thread;

public class RunnableDemo implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "--子线程");

        }
    }

    public static void main(String[] args) throws CloneNotSupportedException {
        RunnableDemo thread2 = new RunnableDemo();
        new Thread(thread2).start();

        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "--主线程");
        }

    }


}

1.3实现Callable接口

package com.yg.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class CallableDemo implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {

        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "----》实现Callable");
        }
        return 100;
    }

    public static void main(String[] args) {
        CallableDemo thread3 = new CallableDemo();
        FutureTask<Integer> futureTask = new FutureTask<>(thread3);
        new Thread(futureTask).start();
        for (int i = 0; i < 100; i++) {
            System.out.println(Thread.currentThread().getName() + "--主线程");
        }


        Integer integer = null;
        try {
            //todo 获取返回值
            integer = futureTask.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("--------==========" + integer);

    }

}

2.线程方法

2.1join线程

package com.yg.thread;

/**
 * @author yuguang
 * @date 2021/3/24 10:03
 * @description 使用场景:某个任务是分阶段的,一个阶段任务完不成,不能进入下一个阶段。
 */
public class JoinThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i <5; i++) {
            System.out.println(Thread.currentThread().getName() + "----" + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        JoinThread t1 = new JoinThread();
        JoinThread t2 = new JoinThread();
        t2.start();
        t2.join();
        t1.start();
        t1.join(); //todo 按照顺序排队执行,等待该线程死亡。

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

    }
}

 

2.2后台线程-Daemon线程

package com.yg.thread;

/*
后台线程又叫Daemon线程,守护线程,精灵线程。
它的作用是运行于后台,为前台线程提供服务。当所有前台线程执行完毕,后台线程就死亡。
典型的垃圾回收线程就是 一条后台线程。
前台线程执行完毕,后台线程死亡之前还是有个时间差的,在这个时间内,后台线程还可能运行。
特点:
    1、当非守护线程结束以后,程序就结束,Java程序退出,会杀死所有的守护线程。
    2、所有守护线程不适合做一些访问固有资源,比如访问文件,访问数据库等操作,因为可能没执行完成就结束了。
 */
public class DaemonThread extends Thread {

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

    public static void main(String[] args) throws InterruptedException {
        DaemonThread t1 = new DaemonThread();
        t1.setDaemon(true);
        t1.start();
        for (int i = 0; i < 3; i++) {
            System.out.println(Thread.currentThread().getName() + "----" + i);
        }
        
    }
}

 

 

2.3.权重 Priority

package com.yg.thread;

/*
 优先级的级别通常是从1~10的整数,但是不同操作系统有所不同,
 建议你设置的时候用Thread.MAX_PRIORITY和Thread.MIN_PRIORITY。
设置高的优先级代表被线程调度器分配cpu的可能性越大。大多少?不可控。
 */
public class PriorityThread extends Thread {

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

    public static void main(String[] args) throws InterruptedException {
        PriorityThread t1 = new PriorityThread();
        PriorityThread t2 = new PriorityThread();

        //设置优先级只是建议线程调度器尽量先为线程分配cpu
        t1.setPriority(Thread.MAX_PRIORITY);
        t1.start();

        t1.setPriority(Thread.MIN_PRIORITY);
        t2.start();
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "----" + i);
        }
    }
}

 

2.4.wait

package com.yg;

/**
 * @author yuguang
 * @date 2021/3/24 15:04
 * @description
 */
public class WaitThread implements Runnable {
    private Object obj = new Object();

    @Override
    public void run() {
        synchronized (obj) {
            obj.notify(); //唤醒
            System.out.println("线程执行--开始");
            try {
                obj.wait(); //等待
            } catch (InterruptedException e) {
                e.printStackTrace();

            }
            System.out.println("线程执行--结束");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        WaitThread thread = new WaitThread();
        new Thread(thread).start();
        Thread.sleep(1000);
        new Thread(thread).start();

    }
}

2.5.Notify

package com.yg;

/**
 * @author yuguang
 * @date 2021/3/24 15:04
 * @description
 */
public class NotifyThread implements Runnable {

    private Object obj = new Object();
    private Boolean flag = true;

    public void setFlag(Boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag) {
            testWait();
        } else {
            testNotify();
        }
    }

    public void testWait() {
        synchronized (obj) {
            System.out.println("线程执行--开始");
            try {
                obj.wait();  //todo 唤醒之后向后继续执行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程执行--结束");
        }
    }

    public void testNotify() {
        //todo 必须要加上同步锁,否则会报错:java.lang.IllegalMonitorStateException
        synchronized (obj) {
            obj.notify();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        NotifyThread thread = new NotifyThread();

        new Thread(thread).start();

        //睡眠
        Thread.sleep(2000);

        thread.setFlag(false);
        new Thread(thread).start();


    }
}

3.例子

 

3.1.卖票-超卖-使用

  1. 如果去掉synchronized,会出现超卖问题

  2. 如果使用:synchronized方法 或者 synchronized代码块,超卖问题解决



/**
 * 卖票、超卖了
 * 1、线程同步,推荐使用同步方法
 *
 */
public class SaleTickets {

    private int tickets = 10;

    //同步方法
 /*   public synchronized void sale() {
        if (tickets > 0) {
            System.out.println(Thread.currentThread().getName() + "--开始卖票--剩余:" + tickets);
            tickets--;
            System.out.println(Thread.currentThread().getName() + "--售票结束--剩余:" + tickets);
        } else {
            System.out.println(Thread.currentThread().getName() + "--无票了--剩余:" + tickets);
        }
    }*/

    //卖票-同步代码块
    public void sale() {
        synchronized (this) {
            if (tickets > 0) {
                System.out.println(Thread.currentThread().getName() + "--开始卖票--剩余:" + tickets);
                tickets--;
                System.out.println(Thread.currentThread().getName() + "--售票结束--剩余:" + tickets);
            } else {
                System.out.println(Thread.currentThread().getName() + "--无票了--剩余:" + tickets);
            }
        }
    }


}
package com.yg.thread.demo;

/**
 * 卖票、超卖了
 */
public class SaleTicketsThread extends Thread {

    private SaleTickets saleTickets;

    public SaleTicketsThread(SaleTickets saleTickets) {
        this.saleTickets = saleTickets;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            saleTickets.sale();
        }
    }

    public static void main(String[] args) {
        SaleTickets tickets = new SaleTickets();
        //共享一个票箱
        SaleTicketsThread t1 = new SaleTicketsThread(tickets);
        SaleTicketsThread t2 = new SaleTicketsThread(tickets);
        SaleTicketsThread t3 = new SaleTicketsThread(tickets);
        t2.start();
        t3.start();
        t1.start();
    }

}

3.2生产者和消费者

 

商品

package com.yg.producer_consumer;

public class Goods {

    private int id;//编号
    private String name; //名称

    public Goods(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

生产者

package com.yg.producer_consumer;

/**
 * 生产者
 */
public class Producer implements Runnable {

    @Override
    public void run() {
        while (true) {

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }//一秒钟生产一个商品

            synchronized (TestProducerConsumer.queue) {
                if (TestProducerConsumer.queue.size() < TestProducerConsumer.MAX_GOODS) {
                    Goods goods = new Goods(1, "商品1");
                    TestProducerConsumer.queue.add(goods);
                    System.out.println(Thread.currentThread().getName() + "----生产了商品");
                }else {
                    //货架满了,生产者休息
                    try {
                        TestProducerConsumer.queue.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

            }

        }
    }
}

 

消费者

package com.yg.producer_consumer;

/**
 * 消费者
 */
public class Consumer implements Runnable {
    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }//一秒钟 消费一个商品

            synchronized (TestProducerConsumer.queue) {
                //货架不为空就消费
                if (!TestProducerConsumer.queue.isEmpty()) {
                    Goods poll = TestProducerConsumer.queue.poll();
                    System.out.println(Thread.currentThread().getName() + "---取出商品");
                } else {
                    //todo 叫生产者生产
                    TestProducerConsumer.queue.notify();
                }
            }

        }
    }
}

测试

package com.yg.producer_consumer;


import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;

public class TestProducerConsumer {

    public static final int MAX_GOODS = 10; //商品
    public static final int MAX_PRODUCER = 5; //生产者上线
    public static final int MAX_CONSUMER = 4; //消费者上线


    public static Queue<Goods> queue = new ArrayBlockingQueue<>(MAX_GOODS);//货架

    public static void main(String[] args) {
        Producer producer = new Producer();
        Consumer consumer = new Consumer();

        for (int i = 0; i < 5; i++) {
            new Thread(producer, "生产者"+i).start();
        }
        for (int i = 0; i < 1; i++) {
            new Thread(consumer, "消费者"+i).start();
        }
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值