JAVA 多线程基础2

等待和唤醒

wait() 线程等待,等待的过程中,释放锁,需要其他线程调用notify去唤醒
notify()唤醒一个等待的线程,如果有多个线程等待,则随机一条唤醒
notifyAll() 唤醒所有等待的线程

Lock锁

是一个接口

使用

获取 其 实现类 ReentrantLock

方法

lock()获取锁
unlock()释放锁

synchronized 与lock的区别

synchronized:不管是同步代码块还是同步方法,都需要在结束一对{}之后,释放锁对象
Lock:是通过两个方法控制需要被同步的代码,更灵活(两个方法为lock和unlock)

public class MyTicket implements Runnable {
    //定义100张票
    int ticket = 100;

    //创建Lock对象
    Lock lock = new ReentrantLock();

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(100L);

                //获取锁
                lock.lock();
                if (ticket > 0) {
                    System.out.println(Thread.currentThread().getName() + "买了第" + ticket + "张票");
                    ticket--;
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }finally {
                //释放锁
                lock.unlock();
            }

        }
    }
}
public class Test01 {
    public static void main(String[] args) {
        MyTicket myTicket = new MyTicket();

        Thread t1 = new Thread(myTicket, "赵四");
        Thread t2 = new Thread(myTicket, "刘能");
        Thread t3 = new Thread(myTicket, "广坤");

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

Callable

接口,实现多线程的一种方式
Callable是一个接口,类似于Runnable

方法

V call() 设置线程任务,类似于run()方法,与之不同的是call可以throw异常,并且还有返回值

call方法和run方法的区别:
a.相同点:都是设置线程任务的
b.不同点:
call方法有返回值,而且有异常可以throws
run方法没有返回值,而且有异常不可以throws

4.
a.叫做泛型
b.泛型:用于指定我们操作什么类型的数据,<>中只能写引用数据类型,如果泛型不写,默认是Object类型数据
c.实现Callable接口时,指定泛型是什么类型的,重写的call方法返回值就是什么类型的

5.获取call方法返回值: FutureTask<V>
a. FutureTask<V> 实现了一个接口: Future <V>
b. FutureTask<V>中有一个方法:
V get() -> 获取call方法的返回值

public class MyCallable implements Callable<String> {

    @Override
    public String call() throws Exception {
        return "ssssss";
    }
}
public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        MyCallable myCallable = new MyCallable();
        /*
           FutureTask(Callable<V> callable)
         */
        FutureTask<String> futureTask = new FutureTask<>(myCallable);

        //创建Thread对象-> Thread(Runnable target)
        Thread t1 = new Thread(futureTask);
        t1.start();

        //调用get方法获取call方法返回值
        System.out.println(futureTask.get());
    }
}

线程池

容器中有多条线程对象,来了线程任务,直接线程池中获取线程对象,用完还回去。

获取
static ExecutorService newFixedThreadPool(int nThreads)
执行线程任务

Futhre<?> submit(Runnable task) 提交一个Runnable任务用于执行
Future<T> submit(Callable<T> task) 提交一个Callable任务用于执行

返回值接口Futher

用于接收run方法或者call方法返回值的,但是run方法没有返回值,所以可以不用Future接收,执行call方法需要用Future接收

Future中有一个方法:V get() 用于获取call方法返回值

关闭

ExecutorService中的方法:
void shutdown() 启动有序关闭,其中先前提交的任务将被执行,但不会接受任何新任务

练习

需求:创建两个线程任务,一个线程任务完成1-100的和,一个线程任务返回一个字符串

public class MyString implements Callable<String> {
    @Override
    public String call() throws Exception {
        return Thread.currentThread().getName();
    }
}
public class MySum implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            sum+=i;
        }
        return sum;
    }
}
public class Test01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //创建线程池对象
        ExecutorService es = Executors.newFixedThreadPool(2);
        Future<String> f1 = es.submit(new MyString());
        Future<Integer> f2 = es.submit(new MySum());
        System.out.println(f1.get());
        System.out.println(f2.get());
    }
}

学习笔记:视频来源尚硅谷

  • 18
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值