Java创建多线程的3种方式和Java当中的线程池【杭州多测师】【杭州多测师_王sir】

/**
* 创建线程的3种方式
* 1.继承Thread类
* 2.实现Runnable接口
* 3.实现Callable接口
* 4.一个进程可以有多个线程、一个线程对应一个进程
* 5.防止多线程数据共享和超卖 ==》可以加锁、或者加同步代码块==》synchronized (this)
*/
package com.duoceshi.thread;

public class RunningMan extends Thread{

    private String name;

    public RunningMan(String name){  //创建一个构造函数
        this.name = name;  //初始化
    }

    //重写Thread类里面的run方法==》用Ctrl+alt+空格键
    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            System.out.println(this.name + " run " +i+" m");
        }
    }

}
package com.duoceshi.thread;

public class RunningWoman implements Runnable {

    private String name;

    public RunningWoman(String name){
        this.name = name;
    }

    //RunningWoman实现Runnable接口、需要实现接口里面的抽象方法
    public void run() {
        for(int i=0;i<100;i++){
            System.out.println(this.name + " run " + i + " m");
        }

    }
}

 

package com.duoceshi.thread;


/**
 * 创建线程的3种方式
 * 1.继承Thread类
 * 2.实现Runnable接口
 * 3.实现Callable接口
 * 4.一个进程可以有多个线程、一个线程对应一个进程
 * 5.防止多线程数据共享和超卖 ==》可以加锁、或者加同步代码块==》synchronized (this)
 */
public class ThreadTest{
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
//        threadTest.threadTest();
        threadTest.runnableTest();

    }

    public void threadTest(){
        //创建了3个线程
        RunningMan runningMan1 = new RunningMan("博尔特");
        RunningMan runningMan2 = new RunningMan("刘翔");
        RunningMan runningMan3 = new RunningMan("苏炳添");

        runningMan1.start();  //谁先说后看CPU的随机性
        runningMan2.start();
        runningMan3.start();

    }

    public void runnableTest(){
        /**
         * 把RunningWoman的匿名对象作为Thread类的构造函数的参数传入进来
         * 实现Runnable接口优点就是:避免了单继承的局限性、在定义线程的时候建议使用此种方式
         */
        Thread threadA = new Thread(new RunningWoman("博尔特"));
        Thread threadB = new Thread(new RunningWoman("刘翔"));
        Thread threadC = new Thread(new RunningWoman("苏炳添"));

        threadA.start();
        threadB.start();
        threadC.start();
    }
}

 

package com.duoceshi.thread;

/**
 * 开发一个简单的卖票程序、可以实现多个窗口卖票
 * 创建3个线程同时购票
 */
public class Ticket implements Runnable{

    private int ticketNum = 100;  //定义100张火车票  票的库存

    /**
     * 用这种方法有一个问题就是:在线程1购买票的时候CPU已经完成切换去处理线程2购票了
     * 然后如此循环导致还没有做ticketNum减票的操作、这样会导致线程之间会共享一份数据
     * 所以针对这种情况需要进行加锁、或者加入同步代码块
     */
//    public void run() {
//        while (true){
//            try {
//                Thread.sleep(100L);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            if(ticketNum<=0){
//                break;
//            }
//            System.out.println(Thread.currentThread()+"购票后还剩余"+ticketNum);
//            ticketNum --;
//        }
//    }

    public void run() {
        while (true){
            try {
                Thread.sleep(100L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //this表示当前的对象、加锁是为了线程安全当上个线程还没结束的时候先跑完上个线程
            //再跑接下来的线程
            synchronized (this){
                if(ticketNum<=0){
                    break;
                }
                System.out.println(Thread.currentThread().getName()+"卖票、还剩余票数为:"+ticketNum);
                ticketNum --;
            }
        }
    }

}
package com.duoceshi.thread;

public class TicketTest {
    public static void main(String[] args) {

        //创建一个对象、3个线程共享
        Ticket ticket = new Ticket();
        Thread thread1 = new Thread(ticket);
        Thread thread2 = new Thread(ticket);
        Thread thread3 = new Thread(ticket);

        thread1.start();
        thread2.start();
        thread3.start();
    }
}

 

线程池
Java 语言虽然内置了多线程支持,启动一个新线程非常方便,但是,创建线程需要操作系统资源(线程资源,栈空间等),频繁创建和销毁大量线程需要消耗大量时间。
线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。
简单地说,线程池内部维护了若干个线程,没有任务的时候,这些线程都处于等待状态。如果有新任务,就分配一个空闲线程执行。如果所有线程都处于忙碌状态,新任务要么放入队列等待,要么增加一
个新线程进行处理。

四种线程池
Java 通过 Executors 接口提供四种线程池,分别为:
1、 newSingleThreadExecutor
创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序( FIFO , LIFO ,优先级)行。
2、 newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
3、newScheduledThreadPool 创建一个可定期或者延时执行任务的定长线程池,支持定时及周期性任务执行。
4、 newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程池

package com.duoceshi.thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * author:杭州滨江多测师_王sir
 */
public class ThreadPool{
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10 ; i++) {
            RunningWoman runningWoman = new RunningWoman("翠花"+i);
            executorService.submit(runningWoman);
        }
        //关闭线程池
        executorService.shutdown();
    }

}

 

posted @ 2022-08-16 11:38  多测师_王sir  阅读(83)  评论(0编辑  收藏  举报