Java 多线程(1),java多线程
Java 多线程(1),java多线程
Java 多线程(1)
1. 概述
了解操作系统后,想学 Java多线程 好久了。一开始我学习了《Think In Java》中的多线程,真心讲的很好。但是,有的过于深刻。需要,自己慢慢体会、总结。所以,我又入手了《Java 多线程编程核心技术》。打算,回头再看《Think In Java》。
我计划以《Java 多线程编程核心技术》为线,写一下自己对 Java多线程 的理解。
2. Java线程基础
【1】线程安全
引起线程安全问题的主要因素是 不同线程对共享资源的访问 。线程安全是学习 多线程技术 的一个关键问题。
这里需要明白 什么是对资源的共享访问、什么是不共享。看下面的代码:
package Multithreading;
public class MyThread extends Thread{
private int count = 2;
public MyThread(String name){
super();
this.setName(name);
}
@Override
public void run() {
super.run();
while (count > 0){
System.out.println(Thread.currentThread().getName() + "\tCount = " + count);
count--;
}
}
}
package Multithreading;
public class Run {
public static void main(String[] args) {
MyThread myThread0 = new MyThread("线程-0");
MyThread myThread1 = new MyThread("线程-1");
MyThread myThread2 = new MyThread("线程-2");
myThread0.start();
myThread1.start();
myThread2.start();
}
}
很明显,这里为三个线程 访问的是三个不同 的对象。所以,它们之间没有影响,它们坑定线程安全。运行结果如下:
将上面的 Run类
改为如下:
package Multithreading;
public class Run {
public static void main(String[] args) {
MyThread task = new MyThread("线程-0");
new Thread(task).start();
new Thread(task).start();
new Thread(task).start();
}
}
得到如下结果:
可以看到这里的 task对象
不再是 资源与线程两种身份,这里它只作为一种资源。所以,下面创建的三个匿名的线程是对同一个资源进行访问的。所以,结果会发生改变,因为 Count <= 0
后其他的线程也发现并退出了。
共享同一个资源会造成 非线程安全。比如,一个线程正要读某共享的资源,而现在调度到一个新的线程执行,这个新线程正好修改那个共享资源。以后,重新调度到原线程读该共享资源时会发现它不是原来所需要的,这就是所谓的 “读写冲突”。如何解决这样的问题呢,可以通过 加锁 机制。。。
【2】this.getName()
的问题
在《Java 多线程编程核心技术》p17,对 this.getName() 方法有点疑问。于是,写代码测试了一下:
package Multithreading;
public class CountOperate extends Thread {
@Override
public synchronized void run() {
super.run();
System.out.println("CountOperate---begin---CountOperate");
System.out.println("this.getName()\t" + this.getName());
System.out.println("this.isAlive()\t" + this.isAlive());
System.out.println("Thread\t" + Thread.currentThread().getName());
System.out.println("Thread\t" + Thread.currentThread().isAlive());
System.out.println("CountOperate----end----CountOperate");
}
}
package Multithreading;
public class Run {
public static void main(String[] args) {
CountOperate countOperate = new CountOperate();
countOperate.start();
Thread thread1 = new Thread(countOperate);
thread1.start();
}
}
运行结果如下:
分析结果可以看到,Thread类
对线程的命名方式,它是从 Thread-0 开始的。比如这里的第一个 Thread对象countOperate ,它的 getName()
方法返回就是 Thread-0。而,第二个 Thread对象thread1,它的 getName()
方法返回就是 Thread-1。知道了这些后,就可以弄懂书上的结果了。
【3】interrupted()
与 isInterrupted()
为了区别它们,先看看它们的声明
public static boolean interrupted() {
return currentThread().isInterrupted(true); //true 表示清理中断标志
}
public boolean isInterrupted() {
return isInterrupted(false); //false 表示不清理中断标志
}
通过分析它们的声明,可以很清楚的认识它们。interrupted()
是静态方法,它可以用来判断当前运行线程的中断标志,可以在调用 currentThread()
看出来。而且,它还每次都清楚中断标志。对于 isInterrupted()
方法,它是用来判断某个 线程对象 的中断标志,且它并不清理中断标志。
【4】异常法停止中断
停止中断的常用方法!
package Multithreading;
public class MyThread extends Thread{
@Override
public void run() {
super.run();
try {
for (int i = 0; i < 500000; i++) {
System.out.println("i = " + i);
if (this.isInterrupted()) {
System.out.println("已经进入停止状态!我要退出!");
throw new InterruptedException();
}
}
}catch (Exception e){
System.out.println("进入退出异常!");
e.printStackTrace();
}
}
}
//ps:注意这里 try-catch 的位置
package Multithreading;
public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
Thread.sleep(1000);
myThread.interrupt();
}
}
【5】suspend 独占
在《Java 多线程编程核心技术》p38,书中说的不是很清楚(或者我的理解有误)。这里,仍然可以通过在最后使用 thread1.resume()
使得可以继续运行。但是,不建议使用 suspend() 和 resume()
方法。
ps:在《Java 多线程编程核心技术》p40,是有一 很大几率 不打印 main end
。但是还是有几率输出的。为了测试,可以在 i++;
后面添加 Thread.yield()
。
【6】线程优先级的继承特性
对于 继承 的理解。这里的继承是说,新的线程在旧的线程上开启而不同于类的继承。
也就是说,在旧线程里启动的新线程拥有旧线程的优先级。
3. 坚持。。。
第一章的结束,用了一上午效率有点低。
一天进步一点点。。。
相关文章
- 暂无相关文章
用户点评