java 多线程基础

目录

创建线程的四种方式

线程的生命周期

synchronized

Lock

多线程卖票问题

生产者消费者模型


创建线程的四种方式

① 继承Tread类,重写run方法。

② 实现runnable接口,重写run方法。

③ 使用FutureTask,重写callable方法,该方法是有返回值的。

④ 使用线程池。(本文章不做演示)

代码

package com.test;

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

public class MyThread {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // lamdba 表达式
        Thread t1 = new Thread(() -> System.out.println(Thread.currentThread().getId() + ": hello"));
        // 静态内部类
        Thread t2 = new Thread() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getId() + ": hello");
            }
        };
        t1.start();
        t2.start();

        // 使用常规方法
        MyRunnable runnable = new MyRunnable();
        Thread t3 = new Thread(runnable);
        // 静态内部类
        Thread t4 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getId() +": hello");
            }
        });
        // lamdba 表达式
        Thread t5 = new Thread(() -> System.out.println(Thread.currentThread().getId() + ": hello"));
        t3.start();
        t4.start();
        t5.start();

        //创建FutureTask的对象
        FutureTask<String> task =new FutureTask<String>(new MyCallable());
        Thread t6 = new Thread(task);
        t6.start();
        //获取call()方法的返回值,即线程运行结束后的返回值
        String result = task.get();
        System.out.println(result);

    }
}

class MyRunnable implements Runnable {

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getId() + ": hello");
    }
}

class  MyCallable implements Callable {

    @Override
    public Object call() throws Exception {
        System.out.println(Thread.currentThread().getId() + ": hello Callable");
        return "hello Callable";
    }
}

线程的生命周期

 

synchronized

synchronized关键字加在方法上,锁的是方法;加在普通方法上,锁对象可以是this;
加在静态方法上,锁对象可以是 类名.class;

这个地方先简单理解一下这是一个同步锁。原理还可以大做文章深入理解。

Lock

①Lock不是Java语言内置的,synchronized是Java语言的关键字,因此是内置特性。Lock是一个类,通过这个类可以实现同步访问;

②Lock和synchronized有一点非常大的不同,采用synchronized不需要用户去手动释放锁,当synchronized方法或者synchronized代码块执行完之后,系统会自动让线程释放对锁的占用;而Lock则必须要用户去手动释放锁,如果没有主动释放锁,就有可能导致出现死锁现象。

③ReentrantLock,意思是“可重入锁”,关于可重入锁的概念在下一节讲述。ReentrantLock是唯一实现了Lock接口的类,并且ReentrantLock提供了更多的方法。

代码

public class Test {
    private ArrayList<Integer> arrayList =new ArrayList<Integer>();
    private Lock lock =new ReentrantLock();   //注意这个地方
    public static void main(String[] args)  {
        final Test test =new Test();
         
        new Thread(){
            public void run() {
                test.insert(Thread.currentThread());
            };
        }.start();
         
        new Thread(){
            public void run() {
                test.insert(Thread.currentThread());
            };
        }.start();
    }  
     
    public void insert(Thread thread) {
        lock.lock();
        try {
            System.out.println(thread.getName()+"得到了锁");
            for(int i=0;i<5;i++) {
                arrayList.add(i);
            }
        }catch (Exception e) {
            // TODO: handle exception
        }finally {
            System.out.println(thread.getName()+"释放了锁");
            lock.unlock();
        }
    }
}

多线程卖票问题

代码

package com.test;

public class ThreadSellingTickets {
    public static void main(String[] args) {
        SellingTickets st = new SellingTickets();
        Thread t1 = new Thread(st, "张飞");
        Thread t2 = new Thread(st, "刘备");
        Thread t3 = new Thread(st, "关羽");

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

class SellingTickets implements Runnable {
    private int tickets = 100;

    @Override
    public void run() {
        while (true) {
            // synchronized关键字加在方法上,锁的是方法;加在普通方法上,锁对象可以是this;
            // 加在静态方法上,锁对象可以是 类名.class;
            synchronized (this) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖出第" + tickets + "张票");
                    tickets--;
                }
            }
        }
    }
}

生产者消费者模型

代码

待续。。

参考链接(本文仅限个人学习交流,支持原创,侵权必删)

https://www.cnblogs.com/dolphin0520/p/3923167.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值