• 线程概述:

    • 多线程的目的,不是提高程序的执行速度,而是提高程序的使用率(能抢到CPU的可能比较大). 因为线程是CPU调度的基本单位,所以,当一个程序的线程较多的时候就更容易抢到cpu的资源
    • 进程:
      • 运行中的程序,是系统进行资源分配和调度的独立单位
      • 每个进程都有他自己的内存空间和系统资源
    • 线程:
      • 是进程中的单个顺序控制流,是一条执行路径,是cpu调度的基本单位
      • 一个进程如果有多条执行路径,称:多线程
      • 一个进程如果只有一条执行路径,称:单线程
  • 线程生命周期:
  • java中线程概览: [ ps : 图来自郭朝:http://blog.csdn.net/smartbetter/article/details/51335165]
  • 继承Thread类 和 实现Runnable:
 /**
*继承Thread类 和 实现Runnable:
* 1.后者解决了java单继承的局限性
2.后者更适合多个相同的程序代码处理同一个资源的情况,将数据与代码有效分离,体现了java面向对象的思维
*
*有人说:
* 前者是多个线程各自执行各自的任务,
* 后者是多个线程处理相同的任务
*
*一般用后者的人居多,因为更灵活
*/ // 继承Thread类
class MyThread extends Thread{
private static Object shareData; // 实现数据共享
@Overwrite
public void run(){
System.out.println("当前线程是"+Thread.currentThread.getName());
}
}
// 创建线程
class Main{
public static void main(String[] args) {
Thread thread=new MyThread();
Thread thread2=new MyThread();
thread.start(); // 线程开启
thread2.start(); // 线程开启
}
}
  • 实现Runnable创建线程类:

  

 // 实现Runnable创建线程类
class MyRunnable implements Runnable{
private Object shareData; // 实现数据共享
public void run(){
System.out.println("当前线程是"+Thread.currentThread.getName());
}
}
//创建线程
class Main{
public static void main(String[] args) {
// 两个线程将共享shareData共享数据
Runnable runa=new MyRunnable();
Thread thread=new MyThread(runa);
Thread thread2=new MyThread(runa);
thread.start(); // 线程开启
thread2.start(); // 线程开启
}
}
  • 使用Callable 和 Future接口:

  

 /**
* 该代码来源: @蛊惑Into
* Callable 和 Future接口
* Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。
* Callable和Runnable有几点不同:
* (1)Callable规定的方法是call(),而Runnable规定的方法是run().
* (2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。
* (3)call()方法可抛出异常,而run()方法是不能抛出异常的。
* (4)运行Callable任务可拿到一个Future对象,
* Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。
* 通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。
*/
public class CallableAndFuture { public static class MyCallable implements Callable{
private int flag = 0;
public MyCallable(int flag){
this.flag = flag;
}
public String call() throws Exception{
if (this.flag == 0){
return "flag = 0";
}
if (this.flag == 1){
try {
while (true) {
System.out.println("looping.");
Thread.sleep(2000);
}
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
return "false";
} else {
throw new Exception("Bad flag value!");
}
}
} public static void main(String[] args) { // 定义3个Callable类型的任务
MyCallable task1 = new MyCallable(0);
MyCallable task2 = new MyCallable(1);
MyCallable task3 = new MyCallable(2); // 创建一个执行任务的服务
ExecutorService es = Executors.newFixedThreadPool(3);
try {
// 提交并执行任务,任务启动时返回了一个Future对象, // 如果想得到任务执行的结果或者是异常可对这个Future对象进行操作
Future future1 = es.submit(task1);
// 获得第一个任务的结果,如果调用get方法,当前线程会等待任务执行完毕后才往下执行
System.out.println("task1: " + future1.get()); Future future2 = es.submit(task2);
// 等待5秒后,再停止第二个任务。因为第二个任务进行的是无限循环
Thread.sleep(5000);
System.out.println("task2 cancel: " + future2.cancel(true)); // 获取第三个任务的输出,因为执行第三个任务会引起异常
// 所以下面的语句将引起异常的抛出
Future future3 = es.submit(task3);
System.out.println("task3: " + future3.get());
} catch (Exception e){
System.out.println(e.toString());
} // 停止任务执行服务
es.shutdownNow(); } }
  • 线程控制:

  

 // 线程控制

 join()线程---必须等线程th执行完成后才能继续向下执行
...
th.start();
th.join();
... yield()礼让---注意和线程通信中wait()区分,yield将线程放到就绪队列,而wait将其放到阻塞队列
...th.doSomething...
th.yield();
...th.doSomethingElse... sleep()睡眠---线程睡眠,将进入阻塞队列
...doSomething...
Thread.sleep(1000);
...continueDoSomething... setDaemon()后台线程---将线程设置为后台线程,将在前台线程都死亡后自动死亡
....
th.setDaemon(true);
.... setPrority()优先级---设置优先级
...
th.setPrority(5);
th.start();
...
  • 线程同步的3种实现:

  

 /* 线程同步的3种实现:
* 1.同步代码块:锁对象可以是任意对象
synchronized(obj){同步代码块}
* 2.同步方法:
2.1 普通同步方法,锁对象是this
public synchronized void fun(){...}
2.2 静态同步方法,锁对象是.class字节码对象
public static synchronized void fun(){...}
3.同步锁:javaAPI提供了多种锁,如读写锁等,以及一些工具类的锁(同时具有同步和通讯特点)
private Lock lock=new ReentrantLock();
...
lock.lock();
...doSomething...
lock.unLock();
*
*
*以下着重介绍几种工具类的锁使用:
Samaphore
CyclicBarrier
CountDownLatch
*/
/**
* 线程互斥与通信:
* 线程通讯之传统线程通讯: Semaphore信号灯工具
* 传统的互斥,是由线程本身来控制锁的占有和释放,这就导致必须当前线程完成,或是主动让出锁,下一个线程才有机会,
* 而semaphore工具, 提供相当于专门的锁的管理方全权控制索,任何线程的请求都通过管理方的许可,这样就解放了锁的控制权,让多个线程共享锁
*
*共有3盏灯,一次来了10个人,只用其中的3个人能够拿到等,当有灯还回的时候,等候队列的人才有机会拿到灯
*可用于死锁恢复的一些场景
*
* @throws Exception
* @author ware E-mail:
* @version create time: 20172017年3月1日下午11:35:41
*/
public class ThreadCommunication3 { public static void main(String[] args) {
final Semaphore sp=new Semaphore(3, true); ExecutorService pool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) {
Runnable task=new Runnable() {
@Override
public void run() {
try {
sp.acquire(); // 请求锁
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程"+Thread.currentThread().getName()+"已经进入---可用数"+(3-sp.availablePermits())); try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println("线程"+Thread.currentThread().getName()+"准备离开"); sp.release(); //释放锁
}
}; pool.submit(task);
} } } /**
* 线程互斥与通信:
* 线程通讯之传统线程通讯: CyclicBarrier工具
* 所有规定的线程必须都在完成某一项工作之后才能继续下一项工作
*
* 如: 班级郊游,只有所有的人都到了集合点(工作1)才能出发(工作2)
*
* @throws Exception
* @author ware E-mail:
* @version create time: 20172017年3月1日下午11:35:41
*/
public class ThreadCommunication4 { public static void main(String[] args) {
final CyclicBarrier cb=new CyclicBarrier(4); // 约定有多少个人 ExecutorService pool = Executors.newCachedThreadPool(); for (int i = 0; i < 4; i++) {
Runnable task=new Runnable() {
@Override
public void run() { try {
// 第一阶段工作
Thread.sleep((long) (Math.random()*1000));
System.out.println(Thread.currentThread().getName()+"到达集合点,当前共有"+cb.getNumberWaiting()+"人在等待");
cb.await(); // 第二阶段工作
Thread.sleep((long) (Math.random()*1000));
System.out.println(Thread.currentThread().getName()+"出发中"+cb.getNumberWaiting()+"人出发中");
cb.await(); // 第三阶段工作
Thread.sleep((long) (Math.random()*1000));
System.out.println(Thread.currentThread().getName()+"到达景点"+cb.getNumberWaiting()+"人到达景点");
cb.await(); } catch (Exception e) {
e.printStackTrace();
} } }; pool.submit(task);
} } } /**
* 线程互斥与通信:
* 线程通讯之传统线程通讯: CountDownLatch工具
* 如同一个倒计时器,当countDown()到0的时候,所有等该"计时器"的线程都会受到消息
*
* 如: 所有的运动员都在等裁判的命令,裁判一声令下,所有的运动员收到消息开始跑,裁判等到所有的人都跑到终点了才宣布结构
*
* @throws Exception
* @author ware E-mail:
* @version create time: 20172017年3月1日下午11:35:41
*/
public class ThreadCommunication6 { public static void main(String[] args) {
final CountDownLatch cdOrder=new CountDownLatch(1); // 裁判命令
final CountDownLatch cdAnswer=new CountDownLatch(4); // 运动员的消息状态 ExecutorService pool = Executors.newCachedThreadPool(); // 4个运动员
for (int i = 0; i < 4; i++) {
Runnable task=new Runnable() {
@Override
public void run() { try {
System.out.println(Thread.currentThread().getName()+"---已经准备好了,等待命令"); cdOrder.await(); // 等命令 System.out.println("等到命令并开跑");
Thread.sleep((long) (Math.random()*1000));
System.out.println(Thread.currentThread().getName()+"跑完全程了"); cdAnswer.countDown(); } catch (Exception e) {
e.printStackTrace();
} } }; pool.submit(task);
} // 1个裁判
Runnable coach=new Runnable() {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"准备开炮.....碰...");
cdOrder.countDown();
System.out.println(Thread.currentThread().getName()+"命令已发出,等待结果..."); cdAnswer.await();
System.out.println(Thread.currentThread().getName()+"比赛结束,成绩出来了"); } catch (InterruptedException e) {
e.printStackTrace();
} }
};
pool.submit(coach); } }
  • 线程通讯:

  

 /*
*3种线程通讯:
1. 传统线程通讯--wait(),notify();
2. Condition线程通讯;
2. BlockingQueue阻塞队列
*
*/
/**
* 线程互斥与通信:
* 线程通讯之传统线程通讯: wait(),notify(),notifyAll()(必须配合synchronized关键字)
*
*父线程执行10次,
*子线程执行50次
* @author ware E-mail:
* @version create time: 20172017年3月1日下午11:35:41
*/
public class ThreadCommunication {
private static boolean isSub=false; public synchronized void doit(){
while(true){
while(isSub){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10; i++) {
System.out.println("main"+"----------"+i);
}
isSub=true;
this.notify();
} }
public synchronized void doit2(){
while(true){
while(!isSub){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for (int i = 0; i < 50; i++) {
System.out.println("sub"+"----------"+i);
}
isSub=false;
this.notify();
}
} public static void main(String[] args) {
ThreadCommunication tc=new ThreadCommunication(); // 父线程
Thread fatherTh=new Thread(){
@Override
public void run() {
tc.doit();
}
}; // 子线程
Thread sonTh=new Thread(){
@Override
public void run() {
tc.doit2();
}
}; fatherTh.start();
sonTh.start();
}
} /**
* 线程互斥与通信:
* 线程通讯之传统线程通讯: Condition(必须配合Lock使用) * 是对阻塞队列的实现: ArrayBlockQueue
* @throws Exception
* @author ware E-mail:
* @version create time: 20172017年3月1日下午11:35:41
*/
public class ThreadCommunication2 { private static final Lock lock=new ReentrantLock();
private static final Condition notFull=lock.newCondition();
private static final Condition notEmpty=lock.newCondition(); private Object resources[]; int putIndex; // 下一个可取的资源索引
int takeIndex; // 下一个可以存放资源的索引
int count; // 当前总资源数 public ThreadCommunication2(int resourceLimit) {
resources=new Object[resourceLimit];
this.putIndex=0;
this.takeIndex=0;
this.count=0;
} public void put(Object taskResource){
lock.lock();
try {
while(count==resources.length){
notFull.await();
}
System.out.println("-----------------put");
resources[putIndex]=taskResource;
putIndex=(putIndex%resources.length);
count++;
notEmpty.signalAll();
} catch (Exception e) {
e.printStackTrace();
}finally{
lock.unlock();
}
} public Object take(){
Object result=null;
lock.lock();
try {
while(count==0){
notEmpty.await();
}
System.out.println("----------------take");
result=resources[takeIndex];
takeIndex=(takeIndex+1)%resources.length;
count--; notFull.signalAll();
} catch (Exception e) {
e.printStackTrace();
}finally{
lock.unlock();
} return result;
} public static void main(String[] args) {
ThreadCommunication2 tc=new ThreadCommunication2(7); // 资源队列的长度为7 // 开10个放线程
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
tc.put(Thread.currentThread().getName());
}
}).start();
} // 开10个拿线程
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(tc.take());
}
}).start();
}
} } /**
*BlockingQueue阻塞队列
*放线程在队列满的时候直接放弃,通知拿线程,然后进入阻塞队列,
*拿线程在队列空的时候直接放弃,通知放线程,然后进入阻塞队列,
*/
public class DequeueTest { private final static BlockingQueue<Object> queue=new ArrayBlockingQueue<>(5); public static void main(String[] args) throws InterruptedException { // 开10个放线程
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
queue.add(Thread.currentThread().getName());
}
}).start();
} // 开10个拿线程
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(queue.remove());
}
}).start();
} } }
  • 线程数据共享:

  

 /* 线程数据共享:
* 1.多个线程间共享同一个数据:
1.1.多个线程的执行代码相同---多个线程共用一个Runnable的实例, 那么Runnable中的类成员将被共享;
* 1.2.多个线程的执行代码不同---为多个Runnable对象传入同一个实体对象
* 1.3.多个线程的执行代码不同---将多个Runnable设置为内部类,将共享实体设置为外部类成员变量
* 2.一个线程的多个代码块共享一个数据:
* 2.1 将 (线程,数据对象) 放到一个map中,
* 2.2 一般使用java类库提供的ThreadLocal,实现原理同上,但是更优雅,而且会在线程结束后自动清理
*
* 线程间的数据共享比较简单,这里着重介绍线程内的数据共享
*/
/**
* 线程范围内的共享:多个模块在同一个线程中运行时要共享一份数据
*
* 解决方式: 使用ThreadLocal---优雅版---将线程与数据分离
*
* @param
* @return
* @throws Exception
* @author ware E-mail:
* @version create time: 20172017年3月2日上午9:07:16
*/
public class ThreadScopeShared4 {
// private static ThreadLocal<Integer> local=new ThreadLocal<>(); public static void main(String[] args) {
for (int i = 0; i < 3; i++) {
new Thread(new Runnable() {
@Override
public void run() {
// int data=new Random().nextInt();
// local.set(data); ThreadScopeSharedData.getInstance().setAge(new Random().nextInt());
ThreadScopeSharedData.getInstance().setName("vivi");
new A().getNum();
new B().getNum();
}
}).start();
} } static class A{ // 模块A
public void getNum(){
int age=ThreadScopeSharedData.getInstance().getAge();
String name=ThreadScopeSharedData.getInstance().getName();
System.out.println(Thread.currentThread().getName()+"---------"+age);
}
}
static class B{ // 模块B
public void getNum(){
int age=ThreadScopeSharedData.getInstance().getAge();
String name=ThreadScopeSharedData.getInstance().getName();
System.out.println(Thread.currentThread().getName()+"---------"+age);
}
}
} // 专门与线程绑定的对象
class ThreadScopeSharedData{
private ThreadScopeSharedData() {}
public static ThreadScopeSharedData getInstance(){
ThreadScopeSharedData instance=map.get();
if(instance==null){
instance=new ThreadScopeSharedData();
map.set(instance);
}
return instance;
} private static ThreadLocal<ThreadScopeSharedData> map=new ThreadLocal<>(); private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
} }

Normal
0

7.8 磅
0
2

false
false
false

EN-US
ZH-CN
X-NONE

/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin-top:0cm;
mso-para-margin-right:0cm;
mso-para-margin-bottom:10.0pt;
mso-para-margin-left:0cm;
line-height:115%;
mso-pagination:widow-orphan;
font-size:11.0pt;
font-family:"Calibri",sans-serif;
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;}

java多线程一览的更多相关文章

  1. Java 多线程并发编程一览笔录

    Java 多线程并发编程一览笔录 知识体系图: 1.线程是什么? 线程是进程中独立运行的子任务. 2.创建线程的方式 方式一:将类声明为 Thread 的子类.该子类应重写 Thread 类的 run ...

  2. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  3. Java多线程基础知识篇

    这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...

  4. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  5. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  6. Java多线程--让主线程等待子线程执行完毕

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  7. Java多线程 2 线程的生命周期和状态控制

    一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...

  8. java 多线程 1 线程 进程

    Java多线程(一).多线程的基本概念和使用 2012-09-10 16:06 5108人阅读 评论(0) 收藏 举报  分类: javaSE综合知识点(14)  版权声明:本文为博主原创文章,未经博 ...

  9. 一起阅读《Java多线程编程核心技术》

    目录 第一章 Java多线程技能 (待续...)

随机推荐

  1. xdebug.var_display_max_data

    Xdebug Display Full Details on var_dump() Xdebug is an excellent addition to a PHP developers arsena ...

  2. javaEE开发中使用session同步和token机制来防止并发重复提交

    javaEE开发中使用session同步和token机制来防止并发重复提交 通常在普通的操作当中,我们不需要处理重复提交的,而且有很多方法来防止重复提交.比如在登陆过程中,通过使用redirect,可 ...

  3. 升级wamp5集成安装包 php5.2到php5.3

    平时xp下面都使用wamp5集成开发 但php的空间命名需要php5.3 才支持,而且公司系统大部分都使用5.3,很多函数与5.2是不同的 难的在xp下面手动安装,集成包使用很方便,配置,快捷键都很不 ...

  4. 2.3. 实体(Core Data 应用程序实践指南)

    Entity 实体,就像是数据表的映射类.用实体就可以创建托管对象了. 实体需要做的就是设置实体名称.实体属性及属性数据类型. 还可以根据实体配置NSManagedObject的子类(可选),创建子类 ...

  5. ThinkPHP框架开发的应用的标准执行流程

    用户URL请求 调用应用入口文件(通常是网站的index.php) 载入框架入口文件(ThinkPHP.php) 记录初始运行时间和内存开销 系统常量判断及定义 载入框架引导类(Think\Think ...

  6. php中利用array_filter过滤数组为空值

    [导读] 在我们开发过程中,判断数组为空时你会想到什么方法呢?首先想到的应该是empty函数,不过直接用empty函数判断为空是不对的,因为当这个值是多维数的时候,empty结果是有值的.其实我们可以 ...

  7. Flash神奇的视频利器StageVideo

    在过去的几年里,视频已经成为web网页上最主流的趋势之一,这主要是由Adobe Flash Player来推动的.2007年Flash Player 9中引入了H.264和全屏支持技术,通过在web页 ...

  8. 纯CSS3实现不错的表单验证效果

    这是补充HTML5基础知识的系列内容,其他为: 一.HTML5-- 新的结构元素 二.HTML5-- figure.time.details.mark 三.HTML5-- details活学活用 四. ...

  9. SQL SERVER运维日记--收缩数据库

    一个小故事 某天,小王正在和HR妹妹闲聊,正HAPPY时,,突然收到系统告警消息,数据库磁盘被剩余空间500M,OMG,不行,磁盘快满了,要是业务要停了,,那就小王只能删库到跑路了,,, 先检查下,有 ...

  10. JS数组处理

    一.定义数组: 方法1 var myCars=new Array(); myCars[0]="Saab"; myCars[1]="Volvo"; myCars[ ...