多线程的应用

本文介绍了Java中的多线程实现方式,包括继承Thread类和实现Runnable接口,展示了线程休眠、优先级设置以及同步和死锁的概念。还讨论了如何使用ThreadPoolExecutor创建线程池及其执行策略。
摘要由CSDN通过智能技术生成

概述

线程是一个程序内部的一条执行路径,一般的main函数只有一条执行路径,那么这个程序就是单线程的程序。

多线程的实现

多线程实现主要有以下两种方式

方案一:继续Thread类

定义一个子类MyThread继承线程类java.lang.Thread,重写run()方法

创建MyThread类的对象

调用线程对象的start()方法启动线程(启动后还是执行run方法的)

class Hello extends Thread {
 
    private String name;

    public hello(String name) {
        this.name = name;
    }
 
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + "运行     " + i);
        }
    }
 
    public static void main(String[] args) {
        Hello h1=new Hello("A");
        Hello h2=new Hello("B");
        h1.start();
        h2.start();
    }
 
   
}

方案二:通过实现Runnable接口

实现步骤:

定义一个线程任务类MyThread实现Runnable接口,重写run()方法

创建MyThread任务对象

把MyThread任务对象交给Thread处理。

调用线程对象的start()方法启动线程

class MyThread implements Runnable{
 
    private int ticket = 5;  //5张票
 
    public void run() {
        for (int i=0; i<=20; i++) {
            if (this.ticket > 0) {
                System.out.println(Thread.currentThread().getName()+ "正在卖票"+this.ticket--);
            }
        }
    }
}
public class Code {
     
    public static void main(String [] args) {
        MyThread my = new MyThread();
        new Thread(my, "1号窗口").start();
        new Thread(my, "2号窗口").start();
        new Thread(my, "3号窗口").start();
    }
}

线程的休眠

代码演示

class hello implements Runnable {
    public void run() {
        for (int i = 0; i < 3; i++) {
            try {
                Thread.sleep(2000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + i);
        }
    }
 
    public static void main(String[] args) {
        hello he = new hello();
        Thread demo = new Thread(he, "线程");
        demo.start();
    }
}

输出结果:结果每隔2s输出一个

线程的优先级

class hello implements Runnable {
    public void run() {
        for(int i=0;i<5;++i){
            System.out.println(Thread.currentThread().getName()+"运行"+i);
        }
    }
 
    public static void main(String[] args) {
        Thread h1=new Thread(new hello(),"A");
        Thread h2=new Thread(new hello(),"B");
        Thread h3=new Thread(new hello(),"C");
        h1.setPriority(8);
        h2.setPriority(2);
        h3.setPriority(6);
        h1.start();
        h2.start();
        h3.start();
         
    }
}

注意:不要误以为优先级越高就先执行。谁先执行还是取决于谁先去的CPU的资源、

同步和死锁

【问题引出】:比如说对于买票系统,有下面的代码:

package com.stx.threadDemo;

public class Ticket extends Thread{
    private static int ticketNums = 100;
    public static void main(String[] args) {
        Ticket ticket1 = new Ticket();
        Ticket ticket2 = new Ticket();
        Ticket ticket3 = new Ticket();

        ticket1.start();
        ticket2.start();
        ticket3.start();
    }

    @Override
    public void run() {
        while (true) {
            if (ticketNums <=0) {
                System.out.println("票已经售罄!");
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("售票窗口:" + Thread.currentThread().getName() + " 售出一张票," + "剩余票数为:" + (--ticketNums));
        }
    }
   
}


运行结果

【运行结果】:

售票窗口:Thread-2 售出一张票,剩余票数为:2
售票窗口:Thread-0 售出一张票,剩余票数为:1
售票窗口:Thread-1 售出一张票,剩余票数为:0
票已经售罄!
售票窗口:Thread-2 售出一张票,剩余票数为:-1
售票窗口:Thread-0 售出一张票,剩余票数为:-2
票已经售罄!
票已经售罄!

这里出现了-1,-2,显然这个是错的。,应该票数不能为负值。

如果想解决这种问题,就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行,

其他的线程必须等到这个线程结束之后才能继续执行。

【同步代码块】:

语法格式:

synchronized(同步对象){

 //需要同步的代码

}

正确代码演示:

package com.stx.threadDemo;

public class Ticket extends Thread{
    private static int ticketNums = 100;
    public static void main(String[] args) {
        Ticket ticket1 = new Ticket();
        Ticket ticket2 = new Ticket();
        Ticket ticket3 = new Ticket();

        ticket1.start();
        ticket2.start();
        ticket3.start();
    }

    @Override
    public void run() {
        while (true) {
            synchronized (Ticket.class){


            if (ticketNums <=0) {
                System.out.println("票已经售罄!");
                break;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("售票窗口:" + Thread.currentThread().getName() + " 售出一张票," + "剩余票数为:" + (--ticketNums));
        }
    }
    }
}


线程池

ThreadPoolExecutor构造器的参数说明

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,    BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,  RejectedExecutionHandler handler) 

代码演示:

1 创建任务

public class MyRunnable implements Runnable{
    @Override
    public void run() {
            System.out.println(Thread.currentThread().getName() + "输出了:HelloWorld ==> ");
           }
}

2 创建线程池并执行

ExecutorService pool = new ThreadPoolExecutor(3, 5 ,
                6, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5) , Executors.defaultThreadFactory(),
               new ThreadPoolExecutor.AbortPolicy() );
  Runnable target = new MyRunnable();
        pool.execute(target);
        pool.execute(target);
        pool.execute(target);

执行策略说明:

(1)当前运行的线程数少于 corePoolSize ,则添加新的线程执行该任务。

(2)当前的线程数等于 corePoolSize ,同时阻塞队列未满,则将任务入队列,而不添加新的线程。

(3)阻塞队列已满同时池中的线程数小于maximumPoolSize ,则创建新的临时线程执行任务。 (4)阻塞队列已满同时池中的线程数等于maximumPoolSize ,则根据构造函数中的 handler 指定的策略来拒绝新的任务。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值