多线程-创建线程的四种方式-初识多线程

多线程

进程:进程是资源分配的最小单位,运行的程序就是进程:qq.exe

线程:线程是程序执行的最小单位,也就是cpu调度执行的最小单位,程序中含有多个线程:聊天,视频

真正的多线程应该是多核cpu,单核cpu其实只是在线程间连续切换

多核cpu才可以做到并行

线程的创建(四种方式)

第一种 继承Thread类

package com.itheima.my;

import java.util.concurrent.TimeUnit;

//继承Thread类  重写 run 方法  调用start开启线程
//线程开启不一定立即执行 由cpu来调度
public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            try {
                TimeUnit.MILLISECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread" + i);
        }
    }

    public static void main(String[] args) {

        MyThread myThread = new MyThread();
        myThread.start();
        for (int i = 0; i < 20; i++) {
            try {
                TimeUnit.MILLISECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("main" + i);
        }
    }
}

第二种 实现Runnable接口

/*
    创建多线程程序的第二种方式:实现Runnable接口
    java.lang.Runnable
        Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。
    java.lang.Thread类的构造方法
        Thread(Runnable target) 分配新的 Thread 对象。
        Thread(Runnable target, String name) 分配新的 Thread 对象。

    实现步骤:
        1.创建一个Runnable接口的实现类
        2.在实现类中重写Runnable接口的run方法,设置线程任务
        3.创建一个Runnable接口的实现类对象
        4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        5.调用Thread类中的start方法,开启新的线程执行run方法

    实现Runnable接口创建多线程程序的好处:
        1.避免了单继承的局限性
            一个类只能继承一个类(一个人只能有一个亲爹),类继承了Thread类就不能继承其他的类
            实现了Runnable接口,还可以继承其他的类,实现其他的接口
        2.增强了程序的扩展性,降低了程序的耦合性(解耦)
            实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离(解耦)
            实现类中,重写了run方法:用来设置线程任务
            创建Thread类对象,调用start方法:用来开启新线程
 */
public class Demo01Runnable {
    public static void main(String[] args) {
        //3.创建一个Runnable接口的实现类对象
        RunnableImpl run = new RunnableImpl();
        //4.创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        Thread t = new Thread(run);//打印线程名称
        //5.调用Thread类中的start方法,开启新的线程执行run方法
        t.start();

        for (int i = 0; i <20 ; i++) {
            System.out.println(Thread.currentThread().getName()+"-->"+i);
        }
    }
}
//1.创建一个Runnable接口的实现类
public class RunnableImpl implements Runnable{
    //2.在实现类中重写Runnable接口的run方法,设置线程任务
    @Override
    public void run() {
        for (int i = 0; i <20 ; i++) {
            System.out.println(Thread.currentThread().getName()+"-->"+i);
        }
    }
}
//龟兔赛跑
public class Race implements Runnable {
    private  static String winner;

    @Override
    public void run() {

        for (int i = 0; i <= 100; i++) {
            if (Thread.currentThread().getName().equals("兔子")){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
                boolean b = gameOver(i);
            if (b){
                break;
            }
            System.out.println(Thread.currentThread().getName()+"跑了"+i+"步数");
        }

    }
    private boolean gameOver(int step){
        if (winner!=null) {
            return true;
        }{
            if (step>=100){
                winner=Thread.currentThread().getName();
                System.out.println("winner is "+ winner);
                return true;
            }
        }
        return false;
    }

    public static void main(String[] args) {
        Race race = new Race();
        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
}

第三种 实现Callable接口

 

import java.util.concurrent.Callable;

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


/**
 * 不用lambda表达式,就是这样,先创建一个callable的实现类。
 * @author LENOVO
 */
public class CallableTest implements Callable<Integer>{

    /**重写执行体call()*/
    @Override
    public Integer call() throws Exception {
        int i = 0;
        int target = 10;
        for(;i<target;i++){
            try { TimeUnit.MILLISECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            //当前线程
            System.out.println("当前线程是:::"+Thread.currentThread()
                    +":"+i);
        }
        return i;
    }

    public static void main(String[] args) {

        //创建callable对象
        CallableTest call=new CallableTest();
        FutureTask<Integer> fu=new FutureTask<Integer>(call);
        Thread th=new Thread(fu,"我是fu线程");
        th.start();
        for (int i = 0; i < 30; i++) {
            try { TimeUnit.MILLISECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            //当前线程
            System.out.println(Thread.currentThread().getName()+"当前线程");

        }
    }
}

第四种 使用线程池创建

使用线程池来创建线程的相关问题

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPool {
    public static void main(String[] args) {
        ExecutorService executorService = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(5));
        for (int i = 0; i < 10; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + "执行");
                }
            });
        }
        executorService.shutdown();
    }
}
import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.*;

/**
 * @author name
 * @date 2020/7/22
 * 使用guava来创建
 */
public class GuavaThreadPoolDemo {
    /**
    *为线程池创建的线程命名*/
    private static ThreadFactory  nameDthreadFactory =
            new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();
    private static ExecutorService executorService = new ThreadPoolExecutor(5,5,60, TimeUnit.SECONDS,
            new ArrayBlockingQueue<Runnable>(10),nameDthreadFactory,new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) {
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println("测试一下guava命名的线程"+Thread.currentThread().getName());
                }
            });
        }
        executorService.shutdown();
    }
}

start方法内部是

底层是在内核创建一个线程,线程模型是1:1

syn锁也是在内核线程上锁,属于重量级锁

 

并发问题:买票


/*
    模拟卖票案例
    创建3个线程,同时开启,对共享的票进行出售
 */
//多个线程访问一个资源时,会产生线程安全问题
public class Demo01Ticket {
    public static void main(String[] args) {
        //创建Runnable接口的实现类对象
        RunnableImpl run = new RunnableImpl();
        //创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        Thread t0 = new Thread(run);
        Thread t1 = new Thread(run);
        Thread t2 = new Thread(run);
        //调用start方法开启多线程
        t0.start();
        t1.start();
        t2.start();
    }
}
/*
    实现卖票案例
 */
public class RunnableImpl implements Runnable{
    //定义一个多个线程共享的票源
    private  int ticket = 100;

    //设置线程任务:卖票
    @Override
    public void run() {
        //使用死循环,让卖票操作重复执行
        while(true){
            //先判断票是否存在
            if(ticket>0){
                //提高安全问题出现的概率,让程序睡眠
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //票存在,卖票 ticket--
                System.out.println(Thread.currentThread().getName()+"-->正在卖第"+ticket+"张票");
                ticket--;
            }
        }
    }
}

 

多线程可以通过以下三种方式创建: 1. 实现Runnable接口,并实现run()方法。首先,自定义一个类并实现Runnable接口,然后在该类中实现run()方法。接下来,创建Thread对象,并将实现了Runnable接口的对象作为参实例化该Thread对象。最后,调用Thread的start()方法来启动线程。这种方式的代码示例可以参考引用\[1\]中的代码。 2. 继承Thread类,重写run()方法。Thread类本质上也是实现了Runnable接口的一个实例,它代表了一个线程的实例。通过继承Thread类并重写run()方法,然后调用start()方法来启动线程。这种方式的代码示例可以参考引用\[2\]中的代码。 3. 使用匿名内部类实现多线程。可以直接在创建Thread对象时使用匿名内部类来实现多线程。这种方式可以简化代码,但只能使用一次。具体的代码示例可以参考引用\[3\]中的代码。 总结起来,多线程创建方式有实现Runnable接口、继承Thread类和使用匿名内部类。每种方式都有其适用的场景,可以根据具体需求选择合适的方式创建多线程。 #### 引用[.reference_title] - *1* *2* [初识多线程——创建多线程的三种方式](https://blog.youkuaiyun.com/pizssn/article/details/106382025)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [多线程创建的三种方式](https://blog.youkuaiyun.com/qq_31780525/article/details/54338341)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值