Java并发—简介与线程创建
程序、进程和线程
程序:一段静态的代码,一组指令的有序集合,不运行的话只是一堆代码。
程序并不能单独执行,只有将程序加载到内存中,系统为他分配资源后才能够执行,这种执行的程序称之为进程。也就是说进程是系统进行资源分配和调度的一个独立单位,每个进程都有自己单独的地址空间。所以说程序与进程的区别在于,程序是指令的集合,是进程运行的静态描述文本,而进程则是程序在系统上顺序执行时的动态活动。
进程:运行中的程序称为进程,拥有系统资源(cpu、内存)。
但是进程存在着很多缺陷,主要集中在两点:
- 进程只能在同一时间干一件事情,如果想同时干两件事或多件事情,进程就无能为力了。
- 进程在执行的过程中如果由于某种原因阻塞了,例如等待输入,整个进程就会挂起,其他与输入无关的工作也必须等待输入结束后才能顺序执行。
为了解决上述两点缺陷,引入了线程这个概念。
线程:线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
一个进程可以拥有多个线程,而一个线程必须拥有一个父进程。线程可以拥有自己的堆栈,自己的程序计数器和自己的局部变量,但不能拥有系统资源。它与父进程的其他线程共享该进程的所有资源。
多线程、并行与并发
- 多线程:指的是这个程序(一个进程)运行时产生了不止一个线程
- 并行与并发:
- 并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
- 并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。
- 线程安全:经常用来描绘一段代码。指在并发的情况之下,该代码经过多线程使用,线程的调度顺序不影响任何结果。这个时候使用多线程,我们只需要关注系统的内存,cpu是不是够用即可。反过来,线程不安全就意味着线程的调度顺序会影响最终结果,如不加事务的转账代码:
void transferMoney(User from, User to, float amount){
to.setMoney(to.getBalance() + amount);
from.setMoney(from.getBalance() - amount);
}
- 同步:Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全,来保证结果的准确。如上面的代码简单加入
@synchronized
关键字。在保证结果准确的同时,提高性能,才是优秀的程序。线程安全的优先级高于性能。
线程的生命周期和五种状态
Java线程具有五中基本状态
新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();
就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;
运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:
1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
Java中创建线程
这里介绍两种常见的Java中创建线程的方式。
1.继承Thread类,重写该类的run()方法。
public class MyThread extends Thread{
private int i; @Override
public void run(){
for(i=0;i<10;i++){
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
public class Main {
public static void main(String[] args) {
Thread thread = new MyThread();
thread.start();
}
}
运行结果:
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
2.实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象。
public class MyRunnable implements Runnable{
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println(Thread.currentThread().getName() + " " + i);
}
}
}
public class Main {
public static void main(String[] args) {
Runnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
}
}
运行结果:
Thread-0 0
Thread-0 1
Thread-0 2
Thread-0 3
Thread-0 4
Thread-0 5
Thread-0 6
Thread-0 7
Thread-0 8
Thread-0 9
参考:
Java并发—简介与线程创建的更多相关文章
- Java并发编程之线程创建和启动(Thread、Runnable、Callable和Future)
这一系列的文章暂不涉及Java多线程开发中的底层原理以及JMM.JVM部分的解析(将另文总结),主要关注实际编码中Java并发编程的核心知识点和应知应会部分. 说在前面,Java并发编程的实质,是线程 ...
- Java并发编程:如何创建线程?
Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...
- 【转】Java并发编程:如何创建线程?
一.Java中关于应用程序和进程相关的概念 在Java中,一个应用程序对应着一个JVM实例(也有地方称为JVM进程),一般来说名字默认是java.exe或者javaw.exe(windows下可以通过 ...
- 2、Java并发编程:如何创建线程
Java并发编程:如何创建线程? 在前面一篇文章中已经讲述了在进程和线程的由来,今天就来讲一下在Java中如何创建线程,让线程去执行一个子任务.下面先讲述一下Java中的应用程序和进程相关的概念知识, ...
- Java并发编程:线程的创建
Java并发编程:线程的创建 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} J ...
- Java并发编程:线程池的使用
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程池的使用(转)
Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...
- Java并发编程:线程控制
在上一篇文章中(Java并发编程:线程的基本状态)我们介绍了线程状态的 5 种基本状态以及线程的声明周期.这篇文章将深入讲解Java如何对线程进行状态控制,比如:如何将一个线程从一个状态转到另一个状态 ...
- Java 并发编程:线程间的协作(wait/notify/sleep/yield/join)
Java并发编程系列: Java 并发编程:核心理论 Java并发编程:Synchronized及其实现原理 Java并发编程:Synchronized底层优化(轻量级锁.偏向锁) Java 并发编程 ...
随机推荐
- 汇编里的IMPORT和EXPORT
IMPORT ,定义表示这是一个外部变量的标号,不是在本程序定义的EXPORT ,表示本程序里面用到的变量提供给其他模块调用的.以上两个在汇编和C语言混合编程的时候用到刚看到一篇不错的BLOG,解说C ...
- Linux中如何配置IP
与网络相关的文件:1) /etc/sysconfig/network 设置主机名称及能否启动Network2) /etc/sysconfig/network-scripts/ifcfg-eth ...
- 每天进步一点点——Linux中的文件描写叙述符与打开文件之间的关系
转载请说明出处:http://blog.csdn.net/cywosp/article/details/38965239 1. 概述 在Linux系统中一切皆能够看成是文件,文件又可分为:普通 ...
- Painting Fence
Painting Fence Time Limit:1000MS Memory Limit:524288KB 64bit IO Format:%I64d & %I64u Sub ...
- JQuery IN ACTION读书笔记之一: JQuery选择器
本章关注两个通过$()使用的常用功能: 通过选择器选择DOM元素,创建新DOM元素. 2.1 选择操作元素 JQuery采用了CSS的语法,而CSS的语法你可能已经很熟悉了.当然,JQuery也做了扩 ...
- Spring MVC Xml视图解析器
XmlViewResolver用于在xml文件中定义的视图bean来解析视图名称.以下示例演示如何在Spring Web MVC框架使用XmlViewResolver. XmlViewResolver ...
- with root cause 解决办法
现象:1.工程在启动的时候无异常,当页面加载到包含spring:message标签的页面时,在后台报空指针异常,同时控制 台会显示with root cause提示: 2. ...
- Marple表演电影字幕
119501:15:59,702 --> 01:16:02,782我的幸运死了 而我很清楚是谁杀了她的 (格雷格)My Lucky is dead, and I know perfectly w ...
- ios - UILabel_长按复制
1.添加长按的手势 UILongPressGestureRecognizer *longGesture = [[UILongPressGestureRecognizer alloc] initWith ...
- ios--后台返回信息有字符串和数字组成的,如何获取电话号码,让用户能够点击并且进行拨打?
-(void)callPhone:(NSString*)phoneNumber{ NSString *phoneStr=[NSString stringWithFormat:@"tel:// ...