第一章 java多线程技能

创建线程的两种方式

a.、继承Thread类

b、实现Runable接口

优缺点分析:Thread类实际上也是实现的runable接口,java中只能单继承,因此继承Thread类的话会有局限。

线程的启动顺序

使用多线程技术时,代码的运行结果与代码的执行顺序或者调用顺序无关。是cpu以一种不确定方式或者说是在不确定的时间调用线程中的run方法。

调用start方法时,只是告诉线程规划器该线程已处于就绪状态,可以调用该线程的run方法。因此执行start不代表该线程立即被执行,调用start方法的顺序不代表线程启动的顺序。

多次调用start方法时,会抛出IllegalThreadStateException。

this.getName()和Thread.currentThread().getName()

getName()方法为Thread类中的方法,实现Runable接口的线程对象不能调用此方法。

Thread.currentThread().getName()在两种实现线程的方式中都可以用。

两者是同一个线程对象时,返回结果是一样的。

当将一个Thread对象当做构造参数传递给另一个Thread对象时,this代表传递的这个对象的引用,Thread.currentThread()代表当前的执行线程对象的引用。

例如:

public classmyThreadextendsThread {

publicmyThread() {

System.out.println("构造函数:Thread.currentThread().getName()="+Thread.currentThread().getName());

System.out.println("构造函数:this.getName="+this.getName());

System.out.println("构造函数:this==Thread.currentThread()"+(this==Thread.currentThread()));

}

public voidrun() {

System.out.println(Thread.currentThread().getName());

System.out.println(this.getName());

System.out.println("this==Thread.currentThread()"+(this==Thread.currentThread()));

}

public static voidmain(String[] args) {

Thread thread1 =new myThread();

thread1.setName("b");

Thread thread =newThread(thread1);

thread.setName("a");

thread.start();

}

}

执行结果为:

构造函数:Thread.currentThread().getName()=main

构造函数:this.getName=Thread-0

构造函数:this==Thread.currentThread()false

a

b

this==Thread.currentThread()false

停止线程

a、Thread.stop() 此方法unsafe,已经被废止。因为强制一个线程停止有可能导致一些清理工作无法进行,另外一个情况就是对锁定的对象进行解锁,导致数据得不到同步的处理,出现数据不一致的情况。

b、建议使用Thread.interrupt(),它是给正在执行的线程打了个标记,并没有立刻停止。特殊情况:如果线程sleep后调用interrupt会报异常。如果先调用interrupt再进入睡眠,则会将睡眠之前的代码逻辑执行完,然后进入睡眠时抛出异常。

如果想立刻停止线程有两种方法:结合interrupted()判断是否已经停止,然后抛出异常;结合interrupted()判断是否已经停止,然后return。建议抛出异常,这样可以进行一些其他处理操作。更可控。使用return会造成污染。


c、使用退出标志

this.interrupted()和this.isInterrupted()

this.interrupted为静态方法,作用是判断当前线程是否是中断状态,执行后会将状态标志清除为false;

this.isInterrupted为实例方法,作用是判断Thread对象是否是中断状态。

suspend和resume线程暂停和恢复

这两个方法也已经被废弃。原因和stop相似,容易造成数据不一致,或者锁死公共资源。

yield方法

- 作用是让出cpu。但是让出多长时间不一定,有可能刚刚让出,又马上获得。

守护线程

java中线程分为用户线程和守护线程两种。守护线程通过setDaemon(true)来设置一个线程为守护线程,必需在调用start之前设置,否则抛出异常。作用是守护非守护线程,当进程中没有非守护线程了,守护线程会自动销毁。典型的守护线程有GC(垃圾回收器),servlet容器初始化后生成的服务线程。

获得线程的返回值

第一种方法:通过类变量和方法返回数

publicclassMyThreadextendsThread

{

privateString value;

publicvoidrun()

{

value ="通过成员变量返回数据";

}

publicstaticvoidmain(String[] args)throwsException

{

MyThread thread =newMyThread();

thread.start();

thread.join();

System.out.println("value:"+ thread.value);

}

}

通过join使线程执行从异步变成同步,等线程执行完后获取该线程的变量。

第二种方法:通过实现callable接口

importjava.util.concurrent.Callable;

publicclassMyThread2implementsCallable {

@Override

publicString call()throwsException {

String string="通过实现Callable借口返回";

returnstring;

}

}

publicstaticvoidmain(String[] args) {

ExecutorService executorService=Executors.newCachedThreadPool();

Callable callable=newMyThread2();

Future future=executorService.submit(callable);

try{

if(future.isDone()){

System.out.println(future.get());

}

}catch(Exception e) {

e.printStackTrace();

}

}

必须使用ExecutorService的submit方法来执行,返回一个Future对象。可以使用isDone()方法检测future是否完成,完成后可以调用get()方法获得future的值,如果直接调用get()方法,get()方法将阻塞值线程结束。

线程池

类的继承关系:

ThreadPoolExcuter--->AbstractExcuterService-->ExcuterService-->Excuter

构造器参数:

a、 corePoolSize  核心池线程数。创建线程池后,默认里面是空的,知道有任务进来,开始创建线程。可以调用pre方法预先生成corePoolSize个线程。创建的线程数大于corePoolSize时,则会把任务放进缓存队列中。

b、 maximumPoolSize最大线程数 

c、 keepAliveTime  线程存活时长 。表示线程没有任务执行时最多保持多久时间会终止。默认情况下,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;

d、unit:参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性。

e、workQueue:一个阻塞队列,用来存储等待执行的任务,这个参数的选择也很重要,会对线程池的运行过程产生重大影响,一般来说,这里的阻塞队列有以下几种选择:

ArrayBlockingQueue;

LinkedBlockingQueue;

SynchronousQueue;

f、threadFactory:线程工厂,主要用来创建线程;

g、handler:表示当拒绝处理任务时的策略,有以下四种取值:

ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。

ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。

ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)

ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容