前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >多线程?怎么用?

多线程?怎么用?

作者头像
故里
发布2020-11-25 15:50:12
2K0
发布2020-11-25 15:50:12
举报
文章被收录于专栏:故里学Java

Java线程:概念与原理

操作系统中线程和进程的概念

现在的操作系统是多任务操作系统。多线程是实现多任务的一种方式。

进程是指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比如在Windows系统中,一个运行的exe就是一个进程。

线程是指进程中的一个执行流程,一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。

进程是系统进行资源分配和调度的独立单位,每一个进程都有它自己的内存空间和系统资源。进程实现多处理机环境下的进程调度,分派,切换时,都需要花费较大的时间和空间开销。为了提高系统的执行效率,减少处理机的空转时间和调度切换的时间,以及便于系统管理,所以有了线程,线程取代了进程了调度的基本功能

使用多线程最主要的原因是提高系统的资源利用率。现在CPU基本都是多核的,如果你只用单线程,那就是只用到了一个核心,其他的核心就相当于空闲在那里了

在平时工作中多线程是随时都可见的。比如说,我们系统Web服务器用的是Tomcat,Tomcat处理每一个请求都会从线程连接池里边用一个线程去处理。又比如说,我们用连接数据库会用对应的连接池,比如Druid/C3P0/DBCP等等,这些都用了多线程的。

除了上面这些框架已经帮我们屏蔽掉「手写」多线程的问题,在我本身的系统也会用到多线程的。比如说:现在要跑一个定时任务,该任务的链路执行时间和过程都非常长,我们这边就用一个线程池将该定时任务的请求进行处理,这样做的好处就是可以及时返回结果给调用方,能够提高系统的吞吐量。

在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口.(其实准确来讲,应该有三种,还有一种是实现Callable接口,并与Future、线程池结合使用,此文这里不讲这个。

Java线程的实现形式

这里继承Thread类的方法是比较常用的一种,如果说你只是想起一条线程。没有什么其它特殊的要求,那么可以使用Thread.

继承Thread类

实现Runnable接口

使用Callable和Future接口创建线程。

main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。

在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个JVM就是在操作系统中启动了一个进程。

什么是线程安全

在我的理解下,在Java世界里边,所谓线程安全就是多个线程去执行某类,这个类始终能表现出正确的行为,那么这个类就是线程安全的。比如我有一个count变量,在service方法不断的累加这个count变量

代码语言:javascript
复制
public class UnsafeCountingServlet extends GenericServlet implements Servlet {
private long count = 0;

public long getCount() {
return count;
}

public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

++count;
// To something else...
}
}

我个人解决线程安全问题的思路有以下:

  • 能不能保证操作的原子性,考虑atomic包下的类够不够我们使用。
  • 能不能保证操作的可见性,考虑volatile关键字够不够我们使用
  • 如果涉及到对线程的控制(比如一次能使用多少个线程,当前线程触发的条件是否依赖其他线程的结果),考虑CountDownLatch/Semaphore等等。
  • 如果是集合,考虑java.util.concurrent包下的集合类。
  • 如果synchronized无法满足,考虑lock包下的类
  • ....

总的来说,就是先判断有没有线程安全问题,如果存在则根据具体的情况去判断使用什么方式去处理线程安全的问题。虽然synchronized很牛逼,但无脑使用synchronized会影响我们程序的性能的。

死锁了解吗?什么情况会造成死锁?

造成死锁的原因可以简单概括为:当前线程拥有其他线程需要的资源,当前线程等待其他线程已拥有的资源,都不放弃自己拥有的资源。避免死锁的方式一般有以下方案:

  1. 固定加锁的顺序“,比如我们可以使用Hash值的大小来确定加锁的先后
  2. 尽可能缩减加锁的范围,等到操作共享变量的时候才加锁。
  3. 使用可释放的定时锁(一段时间申请不到锁的权限了,直接释放掉)

觉得有点东西就点一下“赞和在看”吧!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 故里学Java 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java线程:概念与原理
  • 操作系统中线程和进程的概念
  • Java线程的实现形式
    • 继承Thread类
      • 实现Runnable接口
        • 使用Callable和Future接口创建线程。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档