进程和线程

谈到多线程,就得先讲进程和线程的概念。

进程

进程可以理解为受操作系统管理的基本运行单元。360浏览器是一个进程、WPS也是一个进程,正在操作系统中运行的".exe"都可以理解为一个进程

线程

进程中独立运行的子任务就是一个线程。像QQ.exe运行的时候就有很多子任务在运行,比如聊天线程、好友视频线程、下载文件线程等等。

为什么要使用多线程

如果使用得当,线程可以有效地降低程序的开发和维护等成本,同时提升复杂应用程序的性能。具体说,线程的优势有:

1、发挥多处理器的强大能力

现在,多处理器系统正日益盛行,并且价格不断降低,即时在低端服务器和中断桌面系统中,通常也会采用多个处理器,这种趋势还在进一步加快,因为通过提高时钟频率来提升性能已变得越来越困难,处理器生产厂商都开始转而在单个芯片上放置多个处理器核。试想,如果只有单个线程,双核处理器系统上程序只能使用一半的CPU资源,拥有100个处理器的系统上将有99%的资源无法使用。多线程程序则可以同时在多个处理器上执行,如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率。

2、在单处理器系统上获得更高的吞吐率

如果程序是单线程的,那么当程序等待某个同步I/O操作完成时,处理器将处于空闲状态。而在多线程程序中,如果一个线程在等待I/O操作完成,另一个线程可以继续运行,使得程序能在I/O阻塞期间继续运行。

3、建模的简单性

通过使用线程,可以将复杂并且异步的工作流进一步分解为一组简单并且同步的工作流,每个工作流在一个单独的线程中运行,并在特定的同步位置进行交互。我们可以通过一些现有框架来实现上述目标,例如Servlet和RMI,框架负责解决一些细节问题,例如请求管理、线程创建、负载平衡,并在正确的时候将请求分发给正确的应用程序组件。编写Servlet的开发人员不需要了解多少请求在同一时刻要被处理,也不需要了解套接字的输入流或输出流是否被阻塞,当调用Servlet的service方法来响应Web请求时,可以以同步的方式来处理这个请求,就好像它是一个单线程程序。

4、异步事件的简化处理

服务器应用程序在接受多个来自远程客户端的套接字连接请求时,如果为每个连接都分配其各自的线程并且使用同步I/O,那么就会降低这类程序的开发难度。如果某个应用程序对套接字执行读操作而此时还没有数据到来,那么这个读操作将一直阻塞,直到有数据到达。在单线程应用程序中,这不仅意味着在处理请求的过程中将停顿,而且还意味着在这个线程被阻塞期间,对所有请求的处理都将停顿。为了避免这个问题,单线程服务器应用程序必须使用非阻塞I/O,但是这种I/O的复杂性要远远高于同步I/O,并且很容易出错。然而,如果每个请求都拥有自己的处理线程,那么在处理某个请求时发生的阻塞将不会影响其他请求的处理。

创建线程的方式

创建线程有两种方式:

1、继承Thread,重写父类的run()方法。

public class MyThread00 extends Thread
{
public void run()
{
for (int i = 0; i < 5; i++)
{
System.out.println(Thread.currentThread().getName() + "在运行!");
}
}
}
public static void main(String[] args)
{
MyThread00 mt0 = new MyThread00();
mt0.start(); for (int i = 0; i < 5; i++)
{
System.out.println(Thread.currentThread().getName() + "在运行!");
}
}

看一下运行结果:

main在运行!
Thread-0在运行!
main在运行!
Thread-0在运行!
main在运行!
Thread-0在运行!
main在运行!
Thread-0在运行!
Thread-0在运行!
main在运行!

看到main线程和Thread-0线程交替运行,效果十分明显。

有可能有些人看不到这么明显的效果,这也很正常。所谓的多线程,指的是两个线程的代码可以同时运行,而不必一个线程需要等待另一个线程内的代码执行完才可以运行。对于单核CPU来说,是无法做到真正的多线程的,每个时间点上,CPU都会执行特定的代码,由于CPU执行代码时间很快,所以两个线程的代码交替执行看起来像是同时执行的一样。那具体执行某段代码多少时间,就和分时机制系统有关了。分时系统把CPU时间划分为多个时间片,操作系统以时间片为单位片为单位各个线程的代码,越好的CPU分出的时间片越小。所以看不到明显效果也很正常,一个线程打印5句话本来就很快,可能在分出的时间片内就执行完成了。所以,最简单的解决办法就是把for循环的值调大一点就可以了(也可以在for循环里加Thread.sleep方法,这个之后再说)。

2、实现Runnable接口。和继承自Thread类差不多,不过实现Runnable后,还是要通过一个Thread来启动:

public class MyThread01 implements Runnable
{
public void run()
{
for (int i = 0; i < 5; i++)
{
System.out.println(Thread.currentThread().getName() + "在运行!");
}
}
}
public static void main(String[] args)
{
MyThread01 mt0 = new MyThread01();
Thread t = new Thread(mt0);
t.start(); for (int i = 0; i < 5; i++)
{
System.out.println(Thread.currentThread().getName() + "在运行!");
}
}

效果也十分明显:

main在运行!
Thread-0在运行!
main在运行!
Thread-0在运行!
main在运行!
Thread-0在运行!
main在运行!
Thread-0在运行!
main在运行!
Thread-0在运行!

两种多线程实现方式的对比

看一下Thread类的API:

其实Thread类也是实现的Runnable接口。两种实现方式对比的关键就在于extends和implements的对比,当然是后者好。因为第一,继承只能单继承,实现可以多实现;第二,实现的方式对比继承的方式,也有利于减小程序之间的耦合。

因此,多线程的实现几乎都是使用的Runnable接口的方式。不过,后面的文章,为了简单,就用继承Thread类的方式了。

线程状态

虚拟机中的线程状态有六种,定义在Thread.State中:

1、新建状态NEW

new了但是没有启动的线程的状态。比如"Thread t = new Thread()",t就是一个处于NEW状态的线程

2、可运行状态RUNNABLE

new出来线程,调用start()方法即处于RUNNABLE状态了。处于RUNNABLE状态的线程可能正在Java虚拟机中运行,也可能正在等待处理器的资源,因为一个线程必须获得CPU的资源后,才可以运行其run()方法中的内容,否则排队等待

3、阻塞BLOCKED

如果某一线程正在等待监视器锁,以便进入一个同步的块/方法,那么这个线程的状态就是阻塞BLOCKED

4、等待WAITING

某一线程因为调用不带超时的Object的wait()方法、不带超时的Thread的join()方法、LockSupport的park()方法,就会处于等待WAITING状态

5、超时等待TIMED_WAITING

某一线程因为调用带有指定正等待时间的Object的wait()方法、Thread的join()方法、Thread的sleep()方法、LockSupport的parkNanos()方法、LockSupport的parkUntil()方法,就会处于超时等待TIMED_WAITING状态

6、终止状态TERMINATED

线程调用终止或者run()方法执行结束后,线程即处于终止状态。处于终止状态的线程不具备继续运行的能力

Java多线程1:进程与线程概述的更多相关文章

  1. Java多线程之进程和线程

    在并发编程中有两个基本的概率就是进程和线程.在Java编程中并发编程更多的是关注线程.但是进程也是很重要的. 一个计算机一般会有很多活跃的进程和线程.有一点是没有疑问的在单核系统中,任何时候实际上都是 ...

  2. -1-5 java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁 sleep()和wait()方法的区别 为什么wait(),notify(),notifyAll()等方法都定义在Object类中

     本文关键词: java 多线程 概念 进程 线程区别联系 java创建线程方式 线程组 线程池概念 线程安全 同步 同步代码块 Lock锁  sleep()和wait()方法的区别 为什么wait( ...

  3. Java中的进程和线程

     Java中的进程与线程 一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是 ...

  4. Java中的进程与线程(总结篇)

    详细文档: Java中的进程与线程.rar 474KB 1/7/2017 6:21:15 PM 概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进 ...

  5. Java多线程(一) —— 线程的状态详解

    一.多线程概述  1. 进程 是一个正在执行的程序.是程序在计算机上的一次运行活动. 每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 系统以进程为基本单位进行系统资源的调度 ...

  6. Java多线程(二) —— 线程安全、线程同步、线程间通信(含面试题集)

    一.线程安全 多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的. 讲到线程安全问题,其实是指多线程环境下对共享资源的访问可能会 ...

  7. Java多线程(五)线程的生命周期

    点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...

  8. java 获取当前进程id 线程id

    java  获取当前进程id  线程id RuntimeMXBean (Java Platform SE 8 ) https://docs.oracle.com/javase/8/docs/api/j ...

  9. Java多线程-同步:synchronized 和线程通信:生产者消费者模式

    大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同 ...

随机推荐

  1. DataSet用法详细 转

    DataSet用法详细 转 DataSet用法详细 一.特点介绍 1.处理脱机数据,在多层应用程序中很有用. 2.可以在任何时候查看DataSet中任意行的内容,允许修改查询结果的方法. 3.处理分级 ...

  2. [linux]windows无法访问samba的安全性问题(关闭selinux)

    背景 在某一天重启了虚拟机的 linux 之后,我的 windows 在连接上 samba 之后,点击某些文件夹的时候,会出现没有权限打开的情况.这问题折腾了我一度重新配置了好几次 samba 的配置 ...

  3. HTML5之tabindex属性

    1 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title&g ...

  4. python第三方库学习(2):requests

    Make a Request r = requests.get('https://github.com/timeline.json') Passing Parameters In URLspayloa ...

  5. curl+openssl编译

    curl不支持openssl的静态库,所以编译openssl的时候,应该加上shared 参数,记录一下我亲手编译的参数: ./configure --prefix=/usr/local/openss ...

  6. 自己对Extjs的Xtemplate的忽略

    之前学习extjs Xtmeplate受一些书籍的误导,说Xtemplate不支持else ,今天仔细看了官网的示例,才恍然大悟,卧槽!不仅支持if-elseif-else结构 连switch都能够支 ...

  7. svn服务器搭建与使用

  8. jQuery基础_2

    属性:attr: 属性 , 元素.attr("属性名");获取属性attr("attr","value"): 设置属性attr({value ...

  9. Java中实现PHP中的urlencode与rawurlencode

    php手册中对urlencode这样说明 在java中 URLEncoder做了这样注释 也就是说java中对星号"*"是不进行编码的 也就是说URLEncoder之后还是&quo ...

  10. 电子科技大学第八届ACM趣味程序设计竞赛第四场(正式赛)题解

    A. Picking&Dancing 有一列n个石子,两人交替取石子,每次只能取连续的两个,取走后,剩下的石子仍然排成1列.问最后剩下的石子数量是奇数还是偶数. 读懂题意就没什么好说的. #i ...