Java多线程编程核心技术 第一章笔记

第一章 多线程技能

摘自《Java多线程编程核心技术》一书

线程具有随机特性——使用多线程技术时,代码运行结果与代码执行顺序是无关的。
线程还有不可预知性。

  • CPU随机调用run方法
  • 注意:如果多次调用start方法会出现异常

start()方法通知“线程规划器”,准备就绪,等调用run()方法。
运行顺序:创建对象实例化–>构造方法–>start()–>run()

使用例子:
public class MyThread extends Thread{
    //构造函数
    public MyThread(){
        super();
    }
    @Override
    public void run(){
        super.run();
    }
}

public class Run{
    public static void main(String[] args){
        MyThread a = new MyThread();
        a.start();
    }
}

自定义线程类中的实例变量对其他线程有共享不共享

  • 不共享数据—-多个线程不会同时访问同一个实例变量
  • 共享数据—-多个线程可以同时访问同一个变量

    • 使用关键字上锁synchronized,使抢到的线程完成整个run的操作之后才能被其他线程去抢
    • 不用关键字可能在赋值过程中被插队造成数据混乱
    • 用法:synchronized public void run()
非线程安全

多个线程对同一个对象的同一个实例变量进行操作,导致值被更改、值不同步的情况出现。

i++与println()异常

例子:

run()方法里面
System.out.println("i=" + (i--) + "threadName=" + Thread.currentThread().getName());  

println()在内部是同步的,但是i–会在println()之前发生,所以有概率出现非线程安全问题。

currentThread()方法

获取当前线程的名字Thread.currentThread().getName()

当用start()方法时,run()会自动调用

在main方法中使用run,会由main主线程调用
例:

public static void main(String[] args){
    MyThread mythread = new MyThread();
    myThread.run();
}

isAlive()方法

判断当前是否处于活动状态——已经启动,尚未终止

currentThread()和this的差异

currentThread()是指当前代码段正由那个线程调用

  • MyThread的构造函数由main主线程调用
  • run()是由thread线程调用的,默认名为Thread-0

例子:

public class MyThread02 extends Thread {
    public MyThread02() {
        System.out.println("init curr: " + Thread.currentThread().getName());
        System.out.println("init this: "+this.getName());
    }
    @Override
    public void run() {  
        System.out.println("run curr: " + Thread.currentThread().getName());
        System.out.println("run this: "+this.getName());
    }
}

public class Test02 {
    public static void main(String[] args) {
        MyThread02 target = new MyThread02();
        Thread thread = new Thread(target);
        thread.setName("A");
        thread.start();
    }
}


运行结果
init curr: main
init this: Thread-0
run curr: A
run this: Thread-0  

this其实是Thread类中有一个构造函数:

//传入target,以thread-0为默认初始值
public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

private static int threadInitNumber;
private static synchronized int nextThreadNum() {
     return threadInitNumber++;
}

public void run() {
    if (target != null) {
    target.run();
    }
}

当用Runnable对象作为参数去实例化一个Thread对象时,即在执行run方法中,其实是target在执行的。 this引用的是target
this.getName() = target.getName()–>Thread-0

sleep()方法

在指定毫秒内让正在执行的线程——this.currentThread()休眠

getId()方法

获取线程的id值


线程的停止

interrupt()方法–使线程暂时停止

判断线程是否停止:

  1. interrupted()–判断当前线程是否停止状态

    • 清除状态的功能
    • 第一次用的时候,会把中断状态清除,所以第二次用会返回false
  2. isInterrupted()–判断线程thread对象是否停止状态

    • 没有清除状态的功能

注意:

  • 用stop()是不安全的做法
  • 使用interrupt()只是使线程暂时停止
解决语句继续运行方法–用catch语句停止线程(推荐)

在run方法中用try-catch语句

try{
    for(...){
        if(this.interrupted()){
            System.out.println("已经是停止状态,下一句就是退出了!");
            throw new InterruptedException();
        }
    }

} catch (InterruptedException e){
    System.out.println("被catch了!");
    e.printStackTrace();
}
sleep中停止

在sleep中停止线程(遇到interrupt)会进入catch语句,并清除状态

  • 另一种情况:先interrupt()再sleep,就是先贴上了中断标志,线程还是继续运行的,直到遇到sleep就被catch了。
暴力停止–stop()

可能会抛出java.lang.ThreadDeath异常,可能导致请理性工作得不到完成,或对锁定对象“解锁”,导致数据等不到同步处理,出现数据不一致问题。

  • stop()释放锁可能会导致数据不一致
  • 在JDK被表明是“作废/过期”的方法
使用return停止线程
public void run(){
    while(true){
        if(this.isInterrupted()){
            System.out.println("停止了!");
            return;//此处的return为终止后面的代码执行
        }
        System.out.println("timer="+ System.currentTimeMillis());
    }
}

main方法:
Thread.sleep(2000);
thread.interrupt();

等了2秒之后,贴上中止标志,然后进入if语句,遇到return,线程就停止了。

暂停线程

suspend()暂停线程–过期作废了
resume()恢复线程

  • 这俩方法的缺点
    1. 独占
      • 用suspend暂停上锁synchronized的方法时,其他线程无法访问该方法
    2. 不同步

yield()方法

放弃当前CPU资源,但是不确定放弃多久

划分优先级

优先级有1~10,如果超出范围会抛出异常throw new IllegalArgumentException()

设置优先级–setPriority()
获取优先级–getPriority()

1、优先级具有继承性

在A线程中启动B线程,B的优先级与A一样

2、优先级具有规则性

哪个线程先执行完,和代码调用顺序无关

3、优先级具有随机性

尽量让优先级高的线程先执行,但不是让它执行完再让另一个线程去执行。

优先级高的运行的快

守护线程

当进程中没有非守护线程,守护线程就会自动销毁。
典型的守护线程——垃圾回收线程,最典型的应用——GC(垃圾回收器)

(仅为个人读书总结,有错欢迎指正)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值