说说多线程及创建多线程的四种方式

40 篇文章 3 订阅
13 篇文章 0 订阅

一、线程是什么?
在计算机中当一个程序运行的时候就会创建至少一个进程,例如当我们运行WPS office 的时候,系统就会创建进程来处理我们平时的一些操作,当我们打开任务管理器的时候,在进程的列表里面就可以找到WPS Office.exe的运行程序;
在计算机中处理进程之外还有另一个概念就是线程,线程是存在于进程当中,一个进程可以包含多个线程;当我们的计算机有多核处理器的时候,使用多线程可以加快程序的运算速率;如果一个进程中只有一个线程,当程序遇到一个I/O或网络等其它需要等待的时候,由于程序是单线程的,那么程序只能等待这个运算结束的时候再继续运行,而此时CPU是空闲的,这样会大大的降低程序的效率;当用多个线程的时候,在某个线程遇到比较上述情况的时候,该线程可以继续自己的等待,但是其他的线程也可以使用CPU进行计算,使得CPU一直处于运算状态,这样就会很大的提高程序执行效率;另一方面,多线程可以使用多个处理器核心,来提高运行速度。

二 多线程的四种实现方式

1 继承Thread类,
1)说明:
通过创建Thread类的子类来创建线程。

2)步骤:

(1)创建一个Thread类的子类

(2)重写继承类的run()方法,编写线程执行体

(3)创建线程对象,调用start()方法启动线程 
3) 代码

/**
 * @Description: 多线程实现方式之一:继承thread
 * @Author: Gyl
 * @Time: 2023/01/18
 */
public class CytInheritThread extends Thread{

    @Override
    public void run() {
        //执行线程业务的方法
        for (int i = 0; i < 50; i++) {
            //返回正在执行的线程实例
            Thread thread = Thread.currentThread();
            //getName()获取当前线程实例的名称
            System.out.println(thread.getName()+"我在听音乐-子线程"+i);
        }
    }


}
/**
 * @Description: 多线程实现方式之一:继承thread
 * @Author: Gyl
 * @Time: 2023/01/18
 */
public class CytRealizeInheritThread {
    public static void main(String[] args) {

        CytInheritThread inheritExtendsThread=new CytInheritThread();
        inheritExtendsThread.start();

        for (int i = 0; i < 50; i++) {
            System.out.println("我在看书-主线程"+i);
        }

    }
}

2 实现Runnable接口

1)说明
java是单继承的,在某些情况下一个类可能已经继承了某个父类,这时在用继承Thread类方法来创建线程显然不可能了。
java设计者们提供了另外一个方式创建线程,就是通过实现Runnable接口来创建线程

2)步骤:
(1)创建一个实现Runnable接口的类
(2)在实现类中重写Runnable接口的run方法,设置线程任务。
(3)创建实现类的对象
(4)将此对象作为参数传递到Thread类的构造器中,创建Thread类的对象,通过Thread类的对象调用start()方法

3)代码

/**
 * @Description: 多线程实现方式之二:实现Runnable 调用
 * @Author: Gyl
 * @Time: 2023/01/18
 */
public class CytRunnable implements Runnable {
    @Override
    public void run() {
        //执行线程业务的方法
        for (int i = 0; i < 50; i++) {
            //返回正在执行的线程实例
            Thread thread = Thread.currentThread();
            //getName()获取当前线程实例的名称
            System.out.println(thread.getName()+"我在听音乐-子线程"+i);
        }
    }
}
/**
 * @Description: 多线程实现方式之二:实现Runnable 调用
 * @Author: Gyl
 * @Time: 2023/01/18
 */
public class CytRealizeRunnable {
    public static void main(String[] args) {
        CytRunnable cytRunnable=new CytRunnable();
        cytRunnable.run();
        for (int i = 0; i < 50; i++) {
            System.out.println("我在看书-主线程"+i);
        }
    }
}

4 ) 实现Runnable接口好处
(1).避免了单继承的局限性

java一个类只能继承一个类,类继承了其它的类就不能继承Thread类

如果采用Runnable接口的方式,继承类,也可实现多线程。

(2).增强了程序的扩展性,降低了程序的耦合性(解藕)
a 实现Runnable接口的方式,把设置线程任务和开启新线程进行了分离(解藕)
b 实现类中,重写了run方法,用来设置线程任务
c 创建Thread类对象,调用start方法,用来开启新线程

3 使用callable方式创建线程
1)说明:
使用Callable接口创建线程能够返回数据。与Runnable接口创建线程的方式有点类似,也是需要通过Thread类来创建线程。由于Thread类的构造函数中没有Callable接口,选用了FutureTask类来作为连接创建线程。
 FutureTask类实现了RunnableFuture接口,而RunnableFuture接口继承了Runnable, Future接口。在FutureTask类中构造函数可以传入Callable对象,以此建立关系。
 通过FutureTask中的get()方法来获取Callable接口中的call()方法的返回值。

2)步骤:
1:第一步:继承callable接口并实现call方法,并返回一个sum(随意)值
2:执行Callable方式,需要FutureTask实现类的支持,用于接收运算结果。 FutureTask 是 Future 接口的实现类

3)代码:

import java.util.Random;
import java.util.concurrent.Callable;

/**
 * @Description: 多线程实现方式之三:实现Callable
 * @Author: Gyl
 * @Time: 2023/01/18
 */
public class CytCallable implements Callable {

    @Override
    public Object call() throws Exception {
        //执行线程业务的方法
        for (int i = 0; i < 50; i++) {
            //返回正在执行的线程实例
            Thread thread = Thread.currentThread();
            //getName()获取当前线程实例的名称
            System.out.println(thread.getName()+"我在听音乐-子线程"+i);
        }
        //获取随机数
        Random random = new Random();
        int k=random.nextInt(10);
        return k;
    }
}
import java.util.concurrent.FutureTask;

/**
 * @Description: 多线程实现方式之三:实现Callable
 * @Author: Gyl
 * @Time: 2023/01/18
 */
public class CytRealizeCallable {

    public static void main(String[] args) {
        CytCallable cytCallable = new CytCallable();
        //需要一个callable的实现
        //1、执行callable 方式,需要futuretask实现类的支持,用于接受运算结果
        FutureTask<Integer> fu = new FutureTask<>(cytCallable);
        new Thread(fu).start();
        try {
            int k = fu.get();
            System.out.println(k);
        }catch (Exception e){
            e.printStackTrace();
        }

    }
}

4) 实现runnable和callable的区别
(1) 都是执行多线程,但是方法名称不同 run() 和call()
(2) 实现Runnable方法是没有返回值,无法获取线程业务方法执行结果 而Callable相反
(3) 实现Runnable方法没有抛出异常 而Callable有异常处理,并且获取异常

4 线程池
1)说明:
java线程的创建非常昂贵,需要JVM和OS(操作系统)互相配合完成大量的工作。而java高并发频繁的创建和销毁线程的操作是非常低效的,如何降低java线程的创建成本,就必须要使用到线程池。

合理地使用线程池能够带来3个好处:

第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。

第三:提高线程的可管理性。线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,
还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。

2)创建方式:
创建方式有7种:
(1). Executors.newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待;
(2). Executors.newCachedThreadPool:创建一个可缓存的线程池,若线程数超过处理所需,缓存一段时间后会回收,若线程数不够,则新建线程;
(3). Executors.newSingleThreadExecutor:创建单个线程的线程池,它可以保证先进先出的执⾏顺序;
4. Executors.newScheduledThreadPool:创建一个可以执行延迟任务的线程池;
5. Executors.newSingleThreadScheduledExecutor:创建一个单线程的可以执行延迟任务的线程池。
6. Executors.newWorkStealingPool:创建一个抢占式执行的线程池(任务执⾏顺序不确定)。
7. ThreadPoolExecutor:最原始的创建线程池的⽅式,它包含了 7 个参数可供设置。

3)代码

/**
 * @Description: 多线程实现方式之四:使用线程池
 * @Author: Gyl
 * @Time: 2023/01/18
 */
public class CytPool implements Runnable {

    @Override
    public void run() {
        //执行线程业务的方法
        for (int i = 0; i < 50; i++) {
            //返回正在执行的线程实例
            Thread thread = Thread.currentThread();
            //getName()获取当前线程实例的名称
            System.out.println(thread.getName()+"我在听音乐-子线程"+i);
        }
    }
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * @Description: 多线程实现方式之四:使用线程池
 * @Author: Gyl
 * @Time: 2023/01/18
 */
public class CytRealizePool {

    public static void main(String[] args) {
        //实例化线程类
        CytPool cytPool =new CytPool();
        //使用Executors创建固定长度为4的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        //调用execute启动线程
        executorService.execute(cytPool);
    }
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Python中,多线程共享全局变量需要注意线程安全性。引用中的代码示例展示了在多线程中共享全局变量的情况。在这个例子中,定义了一个全局变量g_num,并在两个线程中修改它的值。然而,由于多线程的执行是并发的,可能会出现竞态条件,导致最终的结果不可预测。 在引用中的第二个例子中,增加了大量的循环来展示竞态条件的问题。两个线程分别对全局变量g_num进行递增操作,但由于线程执行的时机不确定,最终的结果可能不是我们期望的。 为了解决多线程共享变量的竞态条件问题,可以使用锁来保护共享的资源。引用中的代码示例展示了如何使用锁来实现多线程共享变量的安全操作。在这个例子中,使用了threading模块中的Lock类来创建一个锁对象。在对全局变量g_num进行修改之前,先获取锁对象,确保只有一个线程能够修改该变量,然后在修改完成后释放锁,让其他线程可以获取锁进行操作。 总结来,为了确保多线程共享变量的安全操作,可以使用锁来保护共享资源,避免竞态条件的发生。这样可以保证多个线程对同一个全局变量的操作是有序的,避免出现不可预测的结果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [3_python高阶_线程—多线程-共享全局变量](https://blog.csdn.net/brawly/article/details/126734141)[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^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [五分钟,Python 中多线程共享全局变量的问题](https://blog.csdn.net/m0_74872863/article/details/130254062)[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^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Python学习日记-第三十三天-多线程共享全局变量](https://blog.csdn.net/arizia/article/details/127942056)[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^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值