java线程的使用

一、多线程中常用方法

1、Thread 类中的常用 API

1.1、setName (String) 

设置线程的名称

1.2、String getName () 

返回线程的名称

1.3、start() 

启动线程,并执行对象的 run() 方法

1.4、run() 

线程在被调度时执行的操作,子线程要执行的代码放入 run() 方法

1.5、Thread currentThread() 

返回当前线程 。在 Thread 子类中就是 this ,通常用于主线程和 Runnable 实现类

1.6、getPriority()

获取当前线程优先级

1.7、setPriority (int newPriority) 

设置当前线程优先级
线程优先级高,被 CPU 调度的概率大,但不代表一定会运行,还有小概率运行优先级低的线程。

1.8、interrupt() 

中断线程,由运行状态到死亡状态

1.9、isAlive() 

测试线程是否处于活动状态,线程调用 start 后,即处于活动状态

1.10、join(long millis) 

等待该线程终止的时间最长为 millis 毫秒。join() 方法会使当前线程等待调用 join() 方法的线程结束后才能继续执行。注意该方法也需要捕捉异常。

1.11、sleep(long millis) 

睡眠指定时间,程序暂停运行,睡眠期间会让出 CPU 的执行权,去执行其它线程,同时 CPU 也会监视睡眠的时间,一旦睡眠时间到就会立刻执行(因为睡眠过程中仍然保留着锁,有锁只要睡眠时间到就能立刻执行)。

1.12、yield() 

暂停当前正在执行的线程对象,并执行其他线程。

2、Object 类中的常用 API

wait(),notify(),notifyAll() 三个方法是定义在 java.lang.Object 类中的。

2.1、wait()

一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。而当前线程排队等候其他线程调用 notify() 或 notifyAll() 方法唤醒,唤醒后等待重新获得对监视器的所有权后才能继续执行.

2.2、notify()

一旦执行此方法,就会唤醒被 wait 的一个线程。如果有多个线程被 wait,就唤醒优先级高的那个。

2.3、notifyAll()

一旦执行此方法,就会唤醒所有被 wait 的线程。

3、其它

3.1、yield() 和 sleep() 的异同

  • 相同点:yield() 方法和 sleep() 方法类似,也不会释放“锁”。
  • 不同点:yield() 方法只是使当前线程重新回到可执行状态,所以执行 yield() 的线程有可能在进入到可执行状态后马上又被执行。 yield() 方法只能使同优先级或者高优先级的线程得到执行机会,这也和 sleep() 方法不同。

3.2、join() 和 sleep() 的异同

  • 相同点:都可以实现等待
  • 不同点:由于 join 的内部实现是 wait(),所以使用 join() 方法时会释放锁,那么其他线程就可以调用此线程的同步方法了。 sleep() 方法不释放锁,因此线程会一直等待下去,直到任务完成,才会释放锁。

3.3、sleep() 与 wait() 的异同

  • 相同点:一旦执行方法,都可以使得当前的线程进入阻塞状态。
  • 不同点
    • (1)两个方法声明的位置不同:Thread 类中声明 sleep() , Object 类中声明 wait()
    • (2)调用的要求不同:sleep() 可以在任何需要的场景下调用。 wait() 必须使用在同步代码块或同步方法中
    • (3)关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep() 不会释放锁,wait() 会释放锁。
    • (4)当调用某一对象的 wait() 方法后,会使当前线程暂停执行,并将当前线程放入对象等待池中,直到调用了 notify() 方法后,将从对象等待池中移出任意一个线程并放入锁标志等待池中,只有锁标志等待池中的线程可以获取锁标志,它们随时准备争夺锁的拥有权。当调用了某个对象的 notifyAll() 方法,会将对象等待池中的所有线程都移动到该对象的锁标志等待池。

3.4、 Lambda表达式的标准格式

组成Lambda表达式的三要素:形式参数,箭头,代码块
Lambda表达式的格式
①、格式:(形式参数) -> {代码块}
②、形式参数:如果有多个参数,参数之间用逗号隔开;如果没有参数,留空即可
③、->:由英文中画线和大于符号组成,固定写法。代表指向动作
④、代码块:是我们具体要做的事情,也就是以前我们写的方法体内容

        new Thread(()->{
            System.out.println("开始了一个线程"+new Date());
        }).start();

二、java使用多线程的三种方式

  • 继承Thread类,并重写run方法

  • 实现Runnable接口,重写run方法

  • 实现Callable<返回值>接口,重写call方法

 1、继承Thread类,并重写run方法

//开始启动线程

new MyThread().start();

//继承Thread
class MyThread extends Thread{
    @Override
    public void run() {
        int i = 0;
        while (true){
            if (i==40){
                return;
            }
            System.out.println("Thread线程:\t"+i++);
        }
    }
}

2、实现Runnable接口,重写run方法

new Thread(new MyRunnable()).start();

//实现Runnable
class MyRunnable implements Runnable{

    @Override
    public void run() {
        int i = 0;
        while (true){
            if (i==40){
                return;
            }
            System.out.println("Runnable线程:\t"+i++);
        }
    }
}

 3、实现Callable<返回值>接口,重写call方法

Future接口:

可以对具体Runnable、Callable任务的执行结果进行取消、查询是否完成、获取结果等。

FutureTask是Future接口的唯一的实现类。

FutureTask同时实现了Runnable、Future接口,它既可以作为Runnable被线程执行,也可以作为Future得到Callable的返回值。

        MyCallable myCallable = new MyCallable();
        FutureTask<String> futureTask = new FutureTask(myCallable);
        Thread thread = new Thread(futureTask);
        thread.start();
        //get()方法的返回值即为FutureTask构造器参数Callable实现类重写的call()的返回值
        try {
            String o = futureTask.get();
            System.out.println("==="+o+"+==");
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
//Callable
/**
 * 相比于run()方法,call()方法可以有返回值
 * call()方法可以抛出异常,被外面的操作捕获,获取异常的信息
 * Callable支持泛型的返回值
 * 需要借助FutureTask类,比如获取返回结果
 */
class MyCallable implements Callable {
    @Override
    public String call() throws Exception {
        int i = 0;
        while (true){
            if (i==40){
                return "成功执行结束";
            }
            System.out.println("Callable线程:\t"+i++);
        }
    }
}

三、优化表达式

//接口类
interface Like{
    void lamda();
}
//正常实现类
class son1 implements Like{

    @Override
    public void lamda() {
        System.out.println("i'm lamda");
    }
}

静态内部类

public class Test2 {
    static class son2 implements Like{

        @Override
        public void lamda() {
            System.out.println("i'm lamda2");
        }
    }
}

局部内部类

public class Test2 {
    public static void main(String[] args) {
        class son3 implements Like{

            @Override
            public void lamda() {
                System.out.println("i'm lamda3");
            }
        }
    }
}

匿名内部类

public class Test2 {
    public static void main(String[] args) {
        s=new Like() {
            @Override
            public void lamda() {
                System.out.println("i'm Lamda4");
            }
        };
        s.lamda();
    }
}

Lamda

public class Test2 {
    public static void main(String[] args) {
        s= ()-> {
            System.out.println("i'm Lamda5");
        };
        s.lamda();
    }
}

四、买票案例

使用生产者消费者模式。通过缓存区,保证产品数量大于消费数量

//成产者,消费者,产品,缓存区
public class TestPC {
    public static void main(String[] args) {
        Syncontainer syncontainer = new Syncontainer();
        new Productor(syncontainer).start();
        new Consumer(syncontainer).start();

    }
}
//生产者
class Productor extends Thread{
    Syncontainer container;
    public Productor(Syncontainer container)
    {
        this.container=container;
    }
    //生产
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                container.push(new Chicken(i));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("生产了"+(i+1)+"只鸡");
        }
    }
}
//消费者
class Consumer extends  Thread{
    Syncontainer container;
    public Consumer(Syncontainer container)
    {
        this.container=container;
    }
    //消费

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                System.out.println("消费了->"+container.pop().id+"只鸡");
                System.out.println(Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//产品
class Chicken{
    int id;
    Chicken(int id)
    {
        this.id=id;
    }
}
//缓冲区
class Syncontainer{
    //需要一个容器大小
    Chicken[] chickens = new Chicken[10];
    int count =0;
    //生产者放入产品
    public synchronized void push(Chicken chicken) throws InterruptedException {
        //如果容器满了,需要消费者消费
        if(count ==chickens.length)
        {
            this.wait();
        }

        //如果没有满,就需要生产产品放入
        chickens[count] = chicken;
        count++;

        //可以通知消费者了
        this.notifyAll();
    }
    //消费者消费产品
    public synchronized Chicken pop() throws InterruptedException {
        //判断缓冲区是否还有产品
        if(count==0)
        {
            //等待生产者生产,消费者等待
            this.wait();
        }
        count--;
        return chickens[count];
//        this.notifyAll();
        //吃完了,通知生产者生产
    }
}

信号灯法,通过标志为解决

public class TestPC2 {
    public static void main(String[] args) {
        TV tv = new TV();
        new actor(tv).start();
        new watcher(tv).start();
    }
}
//生产者->演员
class actor extends Thread{
    TV tv;
    public actor(TV tv)
    {
        this.tv=tv;
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                if(i%2==0)
                {
                    tv.play("抖音:记录美好生活");
                    System.out.println(i);
                }else{
                    tv.play("快乐大本营");
                    System.out.println(i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//消费者->观众
class watcher extends Thread{
    TV tv;
    public watcher(TV tv)
    {
        this.tv=tv;
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                tv.watch("观众");
                System.out.println(i);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//产品->Tv
class TV{
    String video;
    //    String Watchername;
    boolean flag = true;
    //演员表演,观众等待 T
    //观众观看,演员等待 F
    //表演方法
    public synchronized void play(String vidio) throws InterruptedException {
        //判断如果是true,则表演节目
        if(flag)
        {
            System.out.println("演员表演了->"+vidio);
            Thread.sleep(1000);
            //通知观众观看
            this.notifyAll();   //通知观众观看节目
            this.video=vidio;
            flag=!this.flag;
        }else { //否则,等待观众观看
            this.wait();
        }
    }
    public synchronized void watch(String watchername) throws InterruptedException {
        //判断如果为flase,则观众观看节目
        if(!flag)
        {
            System.out.println(watchername+"观看了"+video);
            Thread.sleep(1000);
            this.notifyAll();
            flag=!flag;
        }else{  //否则等待,直到表演者表演完,再继续观看
            this.wait();
        }
    }
}

通过ReenTrantlock对象进行加锁,解锁


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

/**
 * 买票系统会出现不安全
 * 需要加上锁
 * 通过ReenTrantlock对象进行加锁,解锁
 * private final ReentrantLock locks = new ReentrantLock();
 */
public class TestReentrantLock {
    public static void main(String[] args) {
        buyticket person = new buyticket();
        Thread t = new Thread(person);
        t.start();
        t=new Thread(person);
        t.start();
        t= new Thread(person);
        t.start();
    }

}
//一个卖票的类
class buyticket implements Runnable{
    //Reentrantlock:可重进锁
    private final ReentrantLock locks = new ReentrantLock();
    //票数
    int ticket =10;
    @Override
    //重写的方法
    public void run() {
        while (true)
        {
            try {
                //开启一个锁        开启一个锁最好放在try语句
                locks.lock();
                if(ticket>0)
                {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(ticket--);
                }
                else
                {
                    System.out.println("你买的票已经被购完");
                    break;
                }
            }finally {
                //关闭一个锁
                locks.unlock();
            }
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

༺ཌༀཉི开心豆༃ༀད༻

你的支持是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值