Java多线程核心类Thread(《Java多线程编程核心技术》学习笔记(一))

参考资料 《Java多线程编程核心技术》Java Multi-thread Programming 高洪岩 著

第一章:Java多线程技能

进程与线程的相关知识可以参考浅谈进程和线程
本章主要介绍Thread类的核心方法。
本章的关键技术点:

  1. 线程的启动
  2. 如何使线程暂停
  3. 如何使线程停止
  4. 线程的优先级
  5. 线程安全相关的问题

使用多线程的优点:提升系统的运行效率。

实现多线程的方式(两种)

(一)继承Thread类

//Thread类的定义
public class Thread implements Runnable {
//可以看出,Thread类实现了Runnable接口,它们之间具有多态关系。

该方法缺点:不支持多继承。
继承Thread类的多线程例子:

/**
 * 自定义线程类MyThread.java,此类继承Thread,并且重写run方法。
 * @author Administrator
 *
 */
public class MyThread extends Thread {
	@Override
	public void run() {
		super.run();
		System.out.println("MyThread");
	}
}

/**
 * 运行类
 * @author Administrator
 *
 */
public class Run {
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		myThread.start();
		System.out.println("运行结束!");
	}
}

//运行结果为:
运行结束!
MyThread

从运行结果可以看出,代码的运行结果与代码执行顺序或调用顺序是无关的。即,线程的调用具有随机性。

(二)实现Runnable接口

如果想要创建的线程类已经有一个父类了,这时就不能再继承Thread类了(Java不支持多继承),我们可以使用实现Runnable接口的方法来应对这样的情况。
实现Runnable接口的多线程例子:

/**
 * 实现Runnable接口的类MyRunnable
 * @author Administrator
 *
 */
public class MyRunnable implements Runnable {
	@Override
	public void run() {
		System.out.println("运行中!");
	}
}

/**
 * 运行类
 * @author Administrator
 *
 */
public class Run {
	public static void main(String[] args) {
		Runnable runnable = new MyRunnable();
		Thread thread = new Thread(runnable);
		thread.start();
		System.out.println("运行结束!");
	}
}

//运行结果:
运行结束!
运行中!

Thread.java类也实现了Runnable接口,意味着构造方法Thread(Runnable target)不光可以传入Runnable接口的对象,也可以传入Thread类的对象,这样做完全可以将一个Thread对象中的run()方法交由其他的线程进行调用。
##currentThread()方法
**功能:**返回代码段正在被那个线程调用的信息。

public class MyThread extends Thread {
	public MyThread() {
		System.out.println("构造方法的打印:" + Thread.currentThread().getName());
	}
	
	@Override
	public void run() {
		System.out.println("run方法的打印:" + Thread.currentThread().getName());
	}
}

/*
 * 测试类1
 */
public class Run {
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		myThread.start();
		//myThread.run();
	}
}
//运行结果:
构造方法的打印:main
run方法的打印:Thread-0

/*
 * 测试类2
 */
public class Run {
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		//myThread.start();
		myThread.run();
	}
}
//运行结果:
构造方法的打印:main
run方法的打印:main

*说明:*打印出来的main是一个名称叫作main的线程在执行,跟代码中的main没有任何关系。
##isAlive()方法
**功能:**判断当前的线程是否处于活动状态。
**活动状态:**就是线程已经启动且尚未终止。线程处于正在运行或准备开始运行的状态,就认为线程是“存活”的。

public class MyThread extends Thread {
	@Override
	public void run() {
		System.out.println("run=" + this.isAlive());
	}
}

/*
 * 测试类
 */
public class Run {
	public static void main(String[] args) {
		MyThread myThread = new MyThread();
		System.out.println("begin=" + myThread.isAlive());
		myThread.start();
		System.out.println("end=" + myThread.isAlive());
	}
}
//运行结果:
begin=false
end=true
run=true

*说明:*虽然在上面示例中打印的值为true,但此值是不确定的。打印true值是因为myThread线程还未执行完毕,所以输出true。如果更改代码如下:

/*
 * 测试类
 */
public class Run {
	public static void main(String[] args) throws InterruptedException {
		MyThread myThread = new MyThread();
		System.out.println("begin=" + myThread.isAlive());
		myThread.start();
		Thread.sleep(1000);
		System.out.println("end=" + myThread.isAlive());
	}
}

//运行结果:
begin=false
run=true
end=false

上述代码运行的结果输出为false,因为myThread对象已经在1秒之内执行完毕。
##sleep()方法
**功能:**在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行)。这个“正在执行的线程”是指this.currentThread()返回的线程。
##getId()方法
**功能:**取得线程的唯一标识。

public class Test {
	public static void main(String[] args) throws InterruptedException {
		Thread runThread = Thread.currentThread();
		System.out.println(runThread.getName() + " " + runThread.getId());
	}
}

//运行结果为:
main 1

##停止线程
3种终止正在运行的线程的方法

  1. 使用退出标志,使线程正常退出。即,当run方法完成后线程终止。
  2. 使用stop方法强行终止线程。不推荐使用,stop和suspend及resume方法都已作废过期。
  3. 使用interrupt方法中断线程。调用interrupt()方法仅仅是在当前线程中打了一个停止的标记,并不是真的停止线程。

判断线程的状态是否停止?

  1. this.interrupted():测试当前线程是否已经是中断状态,执行后具有将状态标志清除为false的功能。当前线程是指运行this.interrupted()方法的线程。
  2. this.isInterrupted():测试线程Thread对象是否已经是中断状态,但不清除状态标志。

##暂停线程
暂停线程意味着此线程还可以恢复运行。
使用suspend()方法暂停线程,使用resume()方法恢复线程的执行。
suspend与resume方法的缺点:独占、不同步。
##yield方法
**功能:**放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间。
**缺点:**放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。
##线程的优先级
在操作系统中,线程可以划分优先级,优先级高的线程得到的CPU资源较多,也就是CPU优先执行优先级较高的对象中的任务。
设置线程的优先级使用setPriority()方法。此方法在JDK的源码如下:

public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }

在Java中,线程的优先级分为1~10这10个等级,如果小于1,或大于10,则JDK抛出异常throw new IllegalArgumentException()。
JDK中使用3个常量来预置定义优先级的值。代码如下:

	public final static int MIN_PRIORITY = 1;
    public final static int NORM_PRIORITY = 5;
    public final static int MAX_PRIORITY = 10;
  • **线程优先级具有继承特性:**在Java,线程的优先级具有继承性。比如,A线程启动B线程,则B线程的优先级与A是一样的。

  • **线程优先级具有规则性:**优先级高的线程总是大部分先执行完,但并不是高优先级的线程全部先执行完。当线程优先级的等级差距很大时,谁先执行完和代码的调用顺序无关。

  • **线程优先级具有随机性:**优先级较高的线程不一定每次都先执行完。

  • 线程优先级高的运行得快

##守护线程
在Java线程中有两种线程:用户线程守护线程
守护线程是一种特殊的线程,它的“特性”有陪伴的含义,当进程中不存在非守护线程了,则守护线程自动销毁。典型的守护线程就是垃圾回收线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值