JAVA多线程学习笔记(1)

JAVA多线程学习笔记(1)

因为笔者使用markdown格式书写,后续copy到blog可能存在格式不美观的问题,本文的.mk文件已经上传到我的的github,会进行同步更新。github传送门java

1、建立新进程

因为这部分比较基础,这里不过多赘述,主要以代码呈现git

一、java.lang.Thread的extends

public class MyThread extends Thread {
   public void run() {
      ...
  }
}

public class Main {
   public static void main(String[] args) {
       MyThread t = new MyThread();
       t.start();   //启动新进程,调用run()
      ...
  }
}

二、java.lang中的Runnable接口

public interface Runnable {
   public abstract void run();
}
public class MyRunnable implements Runnable {
   public void run() {
      ...
  }
}
public class Main{
   public static void main(String[] args) {
       /*
        *different to Thread
        *建立MyRunnable的实例,再以该实例为参数建立Thread类的实例
       */
       new Thread(new MyRunnable()).start();      
      ...
  }
}

三、java.util.concurrent.ThreadFactory中的线程建立

java.util.concurrent包中包含抽象化ThreadFactory接口github

ThreadFactory factory = Executors.defaultThreadFactory();
//经过Executors.defaultThreadFactor获取ThreadFactory
factory.newThread(new myRunnable()).start()

2、简单操做和概念简述

具体更加细节的使用会在后面内容中提到,在这里只是作一个简单的罗列和归纳,有一些我本身学习过程当中总结的小提醒。express

(1)Thread.sleep()

线程睡眠 Thread.sleep(long millis) 转到阻塞状态设计模式

try {
   Thread.sleep(10);
} catch (InterruptedException e) {
}
(2)Thread.yield()

sleep 方法使当前运行中的线程睡眼一段时间,进入不可运行状态,且sleep 方法容许较低优先级的线程得到运行机会。安全

yield 方法使当前线程让出 CPU 占有权,但让出的时间是不可设定的。实际上,yield()方法对应了以下操做:先检测当前是否有相同优先级的线程处于同可运行状态,若有,则把 CPU 的占有权交给此线程,不然,继续运行原来的线程。因此yield()方法称为“退让”,它把运行机会让给了同等优先级的其余线程。另外,yield() 方法执行时,当前线程仍处在可运行状态,因此,不可能让出较低优先级的线程些时得到 CPU 占有权。markdown

(3)interrupt()

中断本线程多线程

**本线程中断本身是被容许的,其它线程调用本线程的interrupt()方法时,会经过checkAccess()检查权限。这有可能抛出SecurityException异常。ide

**若是本线程是处于阻塞状态:调用线程的wait(), wait(long)或wait(long, int)会让它进入等待(阻塞)状态,或者调用线程的join(), join(long), join(long, int), sleep(long), sleep(long, int)也会让它进入阻塞状态。性能

**若线程在阻塞状态时,调用了它的interrupt()方法,那么它的“中断状态”会被清除而且会收到一个InterruptedException异常。例如,线程经过wait()进入阻塞状态,此时经过interrupt()中断该线程;调用interrupt()会当即将线程的中断标记设为“true”,可是因为线程处于阻塞状态,因此该“中断标记”会当即被清除为“false”,同时,会产生一个InterruptedException的异常。若是线程被阻塞在一个Selector选择器中,那么经过interrupt()中断它时;线程的中断标记会被设置为true,而且它会当即从选择操做中返回。

**若是不属于前面所说的状况,那么经过interrupt()中断线程时,它的中断标记会被设置为“true”。 中断一个“已终止的线程”不会产生任何操做。

!!!!interrupt()并不会终止处于“运行状态”的线程!它会将线程的中断标记设为true。

(4)synchronized方法(同步方法)
synchronized void method() {
  ...
}
// is equal to
void method() {
   synchronized(this) {
      ...         //synchronized静态方法和动态方法在此例上有所区别,具体请本身查阅资料
  }
}

声明一个方法,表明这个方法只能由一个线程运行

一个实例中的synchronized方法每次只能由一个线程运行,而非synchronized则能够由两个以上线程运行。

一个线程运行一个synchronized方法,则该进程得到了锁,其余进程就没法运行该方法,当该方法完成了,便会释放锁,一个一直等待锁的进程便会得到该锁,开始运行synchronized方法。

而非synchronized方法彻底不受锁的影响,能够自由进入。

注意:每一个实例都拥有一个独立的锁

(5)synchronized代码块
synchronized(expression) {
  ...
}
(6)等待队列

全部实例都拥有一个等待队列,它是在wait方法执行后中止操做的线程的队列

当由其余线程的notify()或notifyAll()方法唤醒,或有其余线程的interrupt()方法唤醒,或wait方法超时时,退出等待队列。

(7)wait

让线程进入等待队列

obj.wait();

若要执行wait方法,进程必须持有锁

(8)notify

从等待队列中取出一个线程(随机的)

线程必须持有要调用的实例的锁

(9)notifyAll

从等待队列中取出全部线程

wait、notify、notifyAll是Object类的方法,也是Thread类的方法

(10)join

等待线程终止

(11)setPriority() 、getPriority()

 

三 、Single Threaded Execution模式

一、synchronized

guarantee that only one thread can enter a given critical section of code

guarantee that all variables accessed inside the synchronized block will be read in from main memory and when the thread exits the synchronized block,all updated variables will be flushed back to main memory

(1)线程互斥处理(lock/unlock)

A得到锁-->A wait()-->A进入等待队列,释放锁-->B得到锁-->B notify()-->A退出等待队列,B仍然持有锁-->B释放锁-->A得到锁,正式开始执行

(2)同步处理

java内存模型确保某个进程进行unlock前全部写入操做对lock的线程可见。

二、SharedResource

在Single Threaded Execution模式中使用到了SharedResource做用的类

SharedResource可被多个线程访问,主要分为safeMethod和unsafeMethod,该模式就是为了保护unsafeMethod,使其同时只能由一个线程访问。

三、什么时候使用

(1)多线程程序

单线程显然不必使用,而且调用synchronized方法比通常方法花费时间更多,会下降程序性能。

引用《图解Java多线程设计模式》中一个不太恰当的例子:在单线程程序中使用synchronized比如一个独居在家的人上厕所关门同样。

(2)SharedResource可能被多个线程访问时
(3)SharedResource的状态会发生变化

例如,Immutable模式就彻底不必使用

(4)须要确保安全性时

java的集合类大多非线程安全,请考虑

能够参考java.util.Collections的API文档

四、性能考虑

程序设计性能仍是不得不考虑的一个环节

该模式主要在两方面会下降程序性能

(1)获取锁的花费
(2)线程conflict

一个小tips:

java.util.Hashtable和java.util.concurrent.ConcurrentHashMap两者功能类似,都是线程安全,其中Hashtable采用Single Threaded Execution模式,更易发生线程冲突,ConcurrentHashMap不易。

相关文章
相关标签/搜索