1.1、概念:

    进程:进程是操作系统结构的基础,是一次程序的执行;是一个程序及其数据再处理器上顺序执行时所发生的活动;是程序再一个数据集合上运行的过程,它是系统进行系统资源分配和调度的最小单元。

    线程:可以理解为一个程序的不同执行路径,是程序执行流的最小单元。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源。一个线程可以创建和撤消另一个线程,同一进程中的多个线程之间可以并发执行。由于线程之间的相互制约,致使线程在运行中呈现出间断性。线程也有就绪阻塞运行三种基本状态。就绪状态是指线程具备运行的所有条件,逻辑上可以运行,在等待处理机;运行状态是指线程占有处理机正在运行;阻塞状态是指线程在等待一个事件(如某个信号量),逻辑上不可执行。每一个程序都至少有一个线程,若程序只有一个线程,那就是程序本身。

1.2、使用多线程

    

 package soarhu;

 /**
* Created by huaox on 2017/4/17.
*
*/
public class Test {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
}
}

输出结果:main

可以知道,在main方法所在的线程即是一个名叫main的线程。

创建线程主要右三种方式:分别为继承Thread类,实现Runnable和Callable接口。

1.2.1:继承Thread

Thread在jdk文档中定义为: public class Thread implements Runnable

   使用从Thread继承的最大局限性即是无法实现多继承,所以可以实现Runnable接口或者Callable接口。

 package soarhu;

 /**
* Created by huaox on 2017/4/17.
*
*/ class ThreadTest extends Thread{ @Override
public void run() {
System.out.println("ThreadTest run method: "+Thread.currentThread().getName());
}
} public class Test {
public static void main(String[] args) {
System.out.println(" main method : "+Thread.currentThread().getName());
Thread thread = new ThreadTest();
thread.start();
System.out.println("end!!!");
}
}

输出结果:

 main method : main

 end!!!
  ThreadTest run method: Thread-0

 从输出结果可以知道:线程之间的代码执行顺序是不可控制的或者说调用顺序是无关的。

1.2.2:实现Runnaball接口

  

package soarhu;

/**
* Created by huaox on 2017/4/17.
*
*/ class ThreadTest implements Runnable{ @Override
public void run() {
System.out.println("ThreadTest run method: "+Thread.currentThread().getName());
}
} public class Test {
public static void main(String[] args) {
System.out.println(" main method : "+Thread.currentThread().getName());
Thread thread = new Thread(new ThreadTest());
thread.start();
System.out.println("end!!!");
}
}

输出结果与上例一致。

1.2.3:实现Callble接口

Callable接口类似于Runnable,但是Runnable不会返回结果,并且无法抛出返回结果的异常,而Callable可以,可以返回值,这个返回值可以被Future拿到。例子如下

package soarhu;

import java.util.concurrent.*;

/**
* Created by huaox on 2017/4/17.
*
*/ class ThreadTest implements Callable<String>{ @Override
public String call() throws Exception {
System.out.println("ThreadTest run method: "+Thread.currentThread().getName());
try {
TimeUnit.MILLISECONDS.sleep(3000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
return "hello";
} } public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException { // 第一种方式:
/*
ExecutorService executor = Executors.newCachedThreadPool();
Future<String> future = executor.submit(new ThreadTest());
System.out.println("result:" + future.get());
executor.shutdown();*/ //第二种方式:
FutureTask<String> futureTask = new FutureTask<String>(new ThreadTest());
Thread thread = new Thread(futureTask);
thread.start();
System.out.println("result:" + futureTask.get());
}
}

输出结果:hello

1.2.4、线程安全

    

package soarhu;

/**
* Created by huaox on 2017/4/17.
*
*/ class ThreadTest implements Runnable{ private int count = 5; @Override
public void run() {
while (count-->0)
System.out.println(Thread.currentThread().getName()+" count:-> "+count);
} } public class Test {
public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread(new ThreadTest(),i+"").start();
}
}
}

输出结果:

0 count:-> 4
2 count:-> 4
1 count:-> 4
1 count:-> 3
1 count:-> 2
1 count:-> 1
1 count:-> 0
2 count:-> 3
2 count:-> 2
2 count:-> 1
2 count:-> 0
0 count:-> 3
0 count:-> 2
0 count:-> 1
0 count:-> 0

程序中的count变量是一个成员变量,如果多个线程同时访问则会出现并发问题,但现在这个程序没有出现安全问题是因为:每个线程都访问自己的变量,互补相关。类似于每个人都卖自己的票。

下面修改为多个线程共卖一张票的情况:

  

package soarhu;

/**
* Created by huaox on 2017/4/17.
*
*/ class ThreadTest implements Runnable{ private int count = 5; @Override
public void run() {
while (count-->0){
Thread.yield();//让给调度器给其他线程执行的机会。此以方法一般用于debug
System.out.println(Thread.currentThread().getName()+" count:-> "+count);
}
} } public class Test {
public static void main(String[] args) {
ThreadTest thread = new ThreadTest();
for (int i = 0; i < 3; i++) {
new Thread(thread,i+"").start();
}
}
}

输出结果:

0 count:-> 4
2 count:-> 2
1 count:-> 2
2 count:-> 0
0 count:-> 1

可见两个线程同时出现了count数为2的情况,也就是两个售货员分别卖出票后,所剩的余票是一样的,这是不允许的,即线程不安全的状况。之所以出现这种情况,是因为某些情况下,i++类似这种操作为非原子操作。可能分为3部分进行。1:获取i的值,2:i+1,3:赋值给i。在这三种情况中。如果有多个线程进行同时访问,那么就会出现安全问题。修改的方式有很多。例如设置为同步块,或者同步方法,显示用Lock锁对象等方式都可以避免。例如:

package soarhu;

/**
* Created by huaox on 2017/4/17.
*
*/ class ThreadTest extends Thread{ private int count = 5; @Override
public void run() {
synchronized (ThreadTest.class) {
if (count-->0) { //此处应该改为if块,如果为while那么其他线程将得不到执行
Thread.yield();//让给调度器给其他线程执行的机会。此以方法一般用于debug
System.out.println(Thread.currentThread().getName() + " count:-> " + count);
}
}
}
} public class Test {
public static void main(String[] args) {
ThreadTest thread = new ThreadTest();
for (int i = 0; i < 5; i++) {
new Thread(thread,i+"").start();
}
}
}

输出结果:

0 count:-> 4
1 count:-> 3
4 count:-> 2
3 count:-> 1
2 count:-> 0

可知现在结果输出一切正常!

1.2.5、关于Thread.currentThread.getName()

package soarhu;

/**
* Created by huaox on 2017/4/17.
*
*/ class ThreadTest extends Thread{ private int count = 5; ThreadTest() {
System.out.println("constructor method start");
System.out.println("-----ThreadCurrent.getName(): "+Thread.currentThread().getName());
System.out.println("------this.getName(): "+this.getName());
System.out.println("constructor method end");
System.out.println("==============================");
} @Override
public void run() {
System.out.println("run method start");
System.out.println("-----ThreadCurrent.getName(): "+Thread.currentThread().getName());
System.out.println("------this.getName(): "+this.getName());
System.out.println("run method end");
System.out.println("=============================="); } } public class Test {
public static void main(String[] args) {
ThreadTest thread = new ThreadTest();
thread.setName("a");
thread.start();
}
}

输出结果:

constructor method start
-----ThreadCurrent.getName(): main
------this.getName(): Thread-0
constructor method end
==============================
run method start
-----ThreadCurrent.getName(): a
------this.getName(): a
run method end
==============================

java多线程基本概述(一)——线程的基本认知的更多相关文章

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

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

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

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

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

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

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

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

  5. Java多线程——<三>简单的线程执行:Executor

    一.概述 按照<Java多线程——<一><二>>中所讲,我们要使用线程,目前都是显示的声明Thread,并调用其start()方法.多线程并行,明显我们需要声明多个 ...

  6. Java多线程——<一>概述、定义任务

    一.概述 为什么使用线程?从c开始,任何一门高级语言的默认执行顺序是“按照编写的代码的顺序执行”,日常开发过程中写的业务逻辑,但凡不涉及并发的,都是让一个任务顺序执行以确保得到想要的结果.但是,当你的 ...

  7. java多线程详解(6)-线程间的通信wait及notify方法

    Java多线程间的通信 本文提纲 一. 线程的几种状态 二. 线程间的相互作用 三.实例代码分析 一. 线程的几种状态 线程有四种状态,任何一个线程肯定处于这四种状态中的一种:(1). 产生(New) ...

  8. java多线程总结五:线程池的原理及实现

    1.线程池简介:     多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.        假设一个服务器完成一项任务所需时间为:T1 创 ...

  9. java多线程(四)-自定义线程池

    当我们使用 线程池的时候,可以使用 newCachedThreadPool()或者 newFixedThreadPool(int)等方法,其实我们深入到这些方法里面,就可以看到它们的是实现方式是这样的 ...

  10. JAVA多线程之当一个线程在执行死循环时会影响另外一个线程吗?

    一,问题描述 假设有两个线程在并发运行,一个线程执行的代码中含有一个死循环如:while(true)....当该线程在执行while(true)中代码时,另一个线程会有机会执行吗? 二,示例代码(代码 ...

随机推荐

  1. 如何快速的学习selenium工具

    分享即快乐. 最近几年,软件测试工程师一度成为热门职业,作为测试员也是倍感压力.作为测试员来说,仅仅会手工测试让职业生涯陷入瓶颈.于是工作之余充电,学习了自动化测试工具selenium,打算进阶中高级 ...

  2. Android中使用开源框架citypickerview实现省市区三级联动选择

    1.概述 记得之前做商城项目,需要在地址选择中实现省市区三级联动,方便用户快速的填写地址,当时使用的是一个叫做android-wheel 的开源控件,当时感觉非常好用,唯一麻烦的是需要自己整理并解析省 ...

  3. 【Unity优化】构建一个拒绝GC的List

    版权声明:本文为博主原创文章,欢迎转载.请保留博主链接:http://blog.csdn.net/andrewfan 上篇文章<[Unity优化]Unity中究竟能不能使用foreach?> ...

  4. 转换器2:ThinkPhp模板转Django模板

    前天写了个<ThinkPhp模板转Flask模板> 居然被同事鄙视了,原因是他用Django,我用Flask,为了避免被他继续安利Django的强大.我决定写一个Django模板转换器. ...

  5. 1050: [HAOI2006]旅行comf

    1050: [HAOI2006]旅行comf Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1495  Solved: 737[Submit][Sta ...

  6. H5 Canvas vs. SVG

    HTML 5 Canvas vs. SVG HTML5 SVG HTML5 地理定位 Canvas 和 SVG 都允许您在浏览器中创建图形,但是它们在根本上是不同的. SVG SVG 是一种使用 XM ...

  7. 解决error104 connection reset by peer;socket error问题

    这个问题原因有两个: 1.因为你访问网站太多次,所以被网站管理员给禁止访问了. 解决方法: 1.延长time.sleep时间 2.设置代理 2.根本没有这个网站.(打开链接检查一下!!!)

  8. React中父组件与子组件之间的数据传递和标准化的思考

    React中父组件与子组件之间的数据传递的的实现大家都可以轻易做到,但对比很多人的实现方法,总是会有或多或少的差异.在一个团队中,这种实现的差异体现了每个人各自的理解的不同,但是反过来思考,一个团队用 ...

  9. 帝国CMS万能标签的使用

    标签名称: 带模板的信息调用标签[万能标签]   [ecmsinfo]栏目ID/专题ID,显示条数,标题截取数,是否显示栏目名,操作类型,标签模板ID,只显示有标题图片[/ecmsinfo] 说明:e ...

  10. background-size IE8兼容方案

    根据canius(http://caniuse.com/#search=background-size),background-size兼容性为IE9以及以上浏览器,如下图所示. 实例代码: < ...