您的位置:首页 > 编程语言 > Java开发

【Java多线程编程核心技术】1.Java多线程技能-笔记总结

2017-11-13 09:10 996 查看
相关链接:

【Java多线程编程核心技术】1.Java多线程技能-笔记总结

【Java多线程编程核心技术】2.对象及变量的并发访问(上)-笔记总结

【Java多线程编程核心技术】2.对象及变量的并发访问(下)-笔记总结

【Java多线程编程核心技术】3.线程间通信 -笔记总结

【Java多线程编程核心技术】4.Lock的使用-笔记总结

【Java多线程编程核心技术】5.定时器Timer-笔记总结

【Java多线程编程核心技术】6.单例模式与多线程-笔记总结

【Java多线程编程核心技术】7.拾遗增补-笔记总结

进程与多线程的概率及线程优点



按【Ctrl+Shift+Esc】 弹出,点击进程选项,这里面的东西就是一个个进程。

进程是受操作系统管理的基本运行单元(原文)

线程则可以理解成为进程中独立运行的子任务,例如在QQ.exe运行时,就有很多子任务在同时允许。如:好友视频线程、下载文件线程、传输数据线程等。

多线程的优势:可以充分的利用计算机cpu的资源。相较于单任务环境,多线程可以来回在多个线程任务间进行切换,避免了在单任务环境下某个任务等待自己所期待的事件而不
4000
能运行时长时间的占用cpu.

使用多线程

一个进程正在运行时至少也有一个进程正在运行,例如学习Java时的用到的第一个方法-main()方法,也是通过一个叫作main的线程执行的

public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
}

输出:main  //这里的main和main方法没有任何关系,仅仅只是同名而已


通过继承Thread类或实现Runnable接口:

public class MyThread extends Thread {
@Override
public void run() {
super.run();
System.out.println("extends Thread");
}
}
public static void main(String[] args) {
MyThread mythread = new MyThread();
mythread.start();
System.out.println("运行结束!");
}

public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("implements Runnable!");
}
}
public static void main(String[] args) {
Runnable runnable=new MyRunnable();
Thread thread=new Thread(runnable);
thread.start();
System.out.println("运行结束!");
}
输出:
运行结束!
extends Thread! 或 implements Runnable!


1.代码的运行结果与代码执行顺序或调用顺序是无关的

2.如果多次调用start()方法,则会出现异常Exception in thread “main” java.lang.IllegalThreadStateException

3.调用start()方法,通知“线程规划器”此线程已经准备就绪,等待调用线程对应的run()方法,如果直接在main()方法里调用run()方法,那就是main线程去执行run方法里的代码,需等run方法执行完以后才能去执行后面的代码,不具备异步执行的效果。

4.执行start()方法的顺序不代码线程启动的顺序

5.Thread类也实现了Runnable接口

Thread构造函数:

public Thread( );
public Thread(Runnable target);
public Thread(String name);
public Thread(Runnable target, String name);
public Thread(ThreadGroup group, Runnable target);
public Thread(ThreadGroup group, String name);
public Thread(ThreadGroup group, Runnable target, String name);
public Thread(ThreadGroup group, Runnable target, String name, long stackSize);


public Thread(Runnable target) 这里不光可以传入一个Runnable接口的对象,还可以传入一个Thread类的对象,也就是完全可以将一个Thread对象中的run方法交由其他的线程进行调用!!!

synchronized关键字:实现同步效果,可以在任意对象及方法上加锁,加锁的这段代码称为“互斥区”或“临界区”。

非线程安全:多个线程对同一个对象的同一个实例进行操作时会出现值被更改、值不同步的情况,进而影响程序执行流程。

print()方法在内部是同步的:

public void println(String x){
synchronized(this){
print(x);
newLine();
}
}


常用API介绍

currentThread():返回代码段正在被哪个线程调用的信息 //Thread.currentThread().getName()

新创建的线程的默认名字为:Thread-X,X代表数字,如Thread-0,Thread-1,Thread-2

isAlive:测试线程是否处于活动状态,就是线程已经启动且尚未终止。

package mythread;
public class CountOperate extends Thread {
public CountOperate() {
System.out.println("CountOperate---begin");
System.out.println("Thread.currentThread().getName()="
+ Thread.currentThread().getName());
System.out.println("Thread.currentThread().isAlive()="
+ Thread.currentThread().isAlive());
System.out.println("this.getName()=" + this.getName());
System.out.println("this.isAlive()=" + this.isAlive());
System.out.println("CountOperate---end");
}
@Override
public void run() {
System.out.println("run---begin");
System.out.println("Thread.currentThread().getName()="
+ Thread.currentThread().getName());
System.out.println("Thread.currentThread().isAlive()="
+ Thread.currentThread().isAlive());
System.out.println("this.getName()=" + this.getName());
System.out.println("this.isAlive()=" + this.isAlive());
System.out.println("run---end");
}
}
public class Run {
public static void main(String[] args) {
CountOperate c = new CountOperate();
Thread t1 = new Thread(c);
System.out.println("main begin t1 isAlive=" + t1.isAlive());
t1.setName("A");
t1.start();
System.out.println("main end t1 isAlive=" + t1.isAlive());
}
}

输出结果:
CountOperate---begin
Thread.currentThread().getName()=main
Thread.currentThread().isAlive()=true
this.getName()=Thread-0
this.isAlive()=false
CountOperate---end
main begin t1 isAlive=false
main end t1 isAlive=true
run---begin
Thread.currentThread().getName()=A
Thread.currentThread().isAlive()=true
this.getName()=Thread-0
this.isAlive()=false
run---end


sleep():在制定的毫秒数内让当前“正在执行的线程”休眠(暂停执行) //Thread.sleep(2000)

getId(): 取得线程的唯一标识。

yield():放弃当前的cpu资源,将它让给其他的任务去占用CPU执行时间,但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。

停止线程

interrupt():在当前线程中打了一个停止的标记,并不是真正的停止线程

interrupted():测试当前线程是否已经中断,执行后具有将状态标志清除为false的功能 //public static boolean interrupted()

isInterrupted():测试线程是否已经中断,但不清除状态标志 //public boolean isInterrupted()

异常法-停止线程

public class MyThread extends Thread {
@Override
public void run() {
super.run();
try {
for (int i = 0; i < 500000; i++) {
if (this.interrupted()) {
System.out.println("已经是停止状态了!我要退出了!");
throw new InterruptedException();
}
System.out.println("i=" + (i + 1));
}
System.out.println("我在for下面");
} catch (InterruptedException e) {
System.out.println("进MyThread.java类run方法中的catch了!");
e.printStackTrace();
}
}
}

public class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(2000);
thread.interrupt();
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("end!");
}
}
i=146942
i=146943
i=146944
i=146945
i=146946
i=146947
i=146948
end!
已经是停止状态了!我要退出了!
进MyThread.java类run方法中的catch了!
java.lang.InterruptedException

at sort.MyThread.run(MyThread.java:12)


在沉睡中停止(sleep()+interrupt()):

public class MyThread extends Thread {
@Override
public void run() {
super.run();
try {
System.out.println("run begin");
Thread.sleep(200000);
System.out.println("run end");
} catch (InterruptedException e) {
System.out.println("在沉睡中被停止!进入catch!当前线程状态:"+this.isInterrupted());
e.printStackTrace();
}
}
}
public class Run {
public static void main(String[] args) {
try {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(200);
thread.interrupt();
} catch (InterruptedException e) {
System.out.println("main catch");
e.printStackTrace();
}
System.out.println("end!");
}

}
run begin
end!
在沉睡中被停止!进入catch!当前线程状态:false
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)

at sort.MyThread.run(MyThread.java:9)


在sleep状态下停止某一线程,会进入catch语句,并清除停止状态值,使之变成false。

同样,先interrupted(),再sleep(),也是同样的效果

暴力停止线程-stop()

当调用stop()时会抛出java.lang.ThreadDeath异常

stop()已经作废,1.可能让一些清理性的工作得不到完成 2.会锁定的对象进行了“解锁”,导致得不到同步处理,导致数据不一致。

用return停止线程(interrupt()+return):

public class MyThread extends Thread {
@Override
public void run() {
while (true) {
if (this.isInterrupted()) {
System.out.println("停止了!");
return;
}
System.out.println("timer=" + System.currentTimeMillis());
}
}
}


建议使用“抛异常”的方法来实现停止线程,因为在catch块中还可以将异常向上抛,使线程停止的事件得以传播

暂停线程

suspend():暂停线程

resume():恢复线程

缺点

1.独占:极易造成公共的同步对象的独占,使其他线程无法访问公共同步对象(尤其注意当与println()方法搭配使用时)

2.不同步

线程的优先级

设置方法-setPriority()

优先级分为1~10,默认值为5 (NORM_PRIORITY=5)

线程优先级的继承特性:例如A线程启动B线程,则B线程的优先级与A是一样的

优先级具有规则性:CPU尽量将执行资源让给优先级比较高的线程

优先级具有随机性:不要把优先级与运行结果的顺序作为衡量的标准,优先级较高的线程并不一定每一次都先执行完run()方法中的任务,线程的优先级与调用run()方法顺序无关

优先级越高,相对越快

守护线程

守护线程:Java中有两种线程,用户线程与守护线程(典型的应用就是垃圾回收器),当进程中不存在非守护线程了,则守护线程自动销毁//这里介绍gc比较少,后面在总结《深入理解Java虚拟机》时会更详细的介绍

Daemon的作用:为其他线程的运行提供便利服务

Mythread thread=new Mythread();
thread.setDaemon(true); //设置为守护线程
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: