多线程常用方法
1、线程命名与获取
多线程的运行状态时不确定的,所以对于多线程的操作必须有一个可以明确标识出线程对象的信息,这个信息通过名称来描述
//获取当前线程名称
//Thread.currentThread().getName()
class MyThread1 implements Runnable{
@Override
public void run() {
for(int i = 0; i < 10; i++){
System.out.println("当前线程名称"+Thread.currentThread().getName()+" ,i = "+i);
}
}
}
public class Test {
public static void main(String[] args) {
MyThread1 myThread = new MyThread1();
//没有设置名称时,系统会自动分配一个名字
new Thread(myThread).start();//没有设置名称
new Thread(myThread).start();//没有设置名称
new Thread(myThread,"线程1").start();//线程命名
}
}
主方法本身就是一个线程,所有的线程都是通过主线程创建并启动的
class MyThread implements Runnable{
@Override
public void run() {
System.out.println("当前线程"+Thread.currentThread().getName());
}
}
public class Test{
public static void main(String[] args) {
MyThread mt = new MyThread();
mt.run();//通过对象名直接调用run()方法
new Thread(mt).start();//通过线程调用
}
}
//当前线程main
//当前线程Thread-0
2、线程休眠操作(sleep()方法)
让线程暂缓执行一段时间,等到了预计时间之后恢复执行
线程休眠会交出CPU,让CPU去执行其他的任务。但不会释放锁,也就是说如果当前线程持有某个对象的锁,即使调用sleep方法,其他线程也无法访问这个对象
//线程休眠操作
class MyThread implements Runnable{
@Override
public void run() {
for(int i = 0; i < 100; i++){
try {
Thread.sleep(1000);//线程休眠1000毫秒
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("当前线程"+Thread.currentThread().getName()+",i = "+i);
}
}
}
public class Test{
public static void main(String[] args) {
MyThread mt = new MyThread();
new Thread(mt).start();//三个线程并发执行
new Thread(mt).start();
new Thread(mt).start();
}
}
3、线程让步yield()方法
暂停当前正在执行的线程对象,并执行其他线程
yield方法与sleep方法类似,让当前线程交出CPU同时不会释放锁,但是yield不能控制具体交出CPU的时间,同时yield方法只能让拥有相同优先级的线程由获取CPU执行机会
//线程让步操作
class MyThread implements Runnable{
@Override
public void run() {
for(int i = 0; i < 5; i++){
Thread.yield();//调用yield方法,使线程重新回到就绪状态
System.out.println("当前线程"+Thread.currentThread().getName()+",i = "+i);
}
}
}
public class Test{
public static void main(String[] args) {
MyThread mt = new MyThread();
new Thread(mt).start();
new Thread(mt).start();
new Thread(mt).start();
}
}
4、等待该线程终止join()方法
如果在主线程中调用此方法就会让主线程休眠,使得调用该方法的线程先执行完毕后在开始执行主线程
//等待该线程终止
class MyThread implements Runnable{
@Override
public void run() {
try{
System.out.println("主线程休眠前的时间");
Test.printTime();
Thread.sleep(200);
System.out.println(Thread.currentThread().getName());
System.out.println("睡眠时间结束");
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
public class Test{
public static void main(String[] args) throws InterruptedException {
MyThread mt = new MyThread();
Thread thread = new Thread(mt,"线程A");
thread.start();
System.out.println(Thread.currentThread().getName());
thread.join();
System.out.println("代码结束");
}
public static void printTime(){
Date date = new Date();
DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(date);
System.out.println(time);
}
}
5、线程停止的三种方式
I、设置标志位使线程正常退出
//设置标志位使线程退出
class MyThread implements Runnable {
private boolean flag = true;//定义标记位
@Override
public void run() {
int i = 1;
while (flag) {
try {
Thread.sleep(100);
System.out.println("第" + i + "次执行,线程名为:" + Thread.currentThread().getName());
i++;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void setFlag(boolean flag){
this.flag = flag;
}
}
public class Test{
public static void main(String[] args) throws InterruptedException {
MyThread mt = new MyThread();
Thread thread = new Thread(mt,"线程A");
thread.start();
Thread.sleep(200);
mt.setFlag(false);
System.out.println("代码结束");
}
}
II、使用stop方法强制退出(不安全)
//使用stop方法强制退出
public static void main(String[] args) throws InterruptedException {
MyThread mt = new MyThread();
Thread thread = new Thread(mt,"线程A");
thread.start();
Thread.sleep(200);
thread.stop();//直接使用stop()方法强制退出
System.out.println("代码结束");
}
III、使用Thread类中的interrupt()方法中断线程
//使用Thread.interrupt()方法使线程退出
class MyThread implements Runnable {
private boolean flag = true;
@Override
public void run() {
int i = 1;
while (flag) {
try {
/**
* 线程在这里阻塞之后,会调用interrupt()方法
* 清除中断标志,抛出异常
*/
Thread.sleep(100);
boolean bool = Thread.currentThread().isInterrupted();
if(bool){
System.out.println("非阻塞状态下执行此操作,线程状态"+bool);
break;
}
System.out.println("第"+i+"次执行,线程名为:"+Thread.currentThread().getName());
i++;
} catch (InterruptedException e) {
System.out.println("退出");
/**
* 这里退出阻塞状态,中断标志被系统自动清除
* flag被重新设置为false
*/
boolean bool = Thread.currentThread().isInterrupted();
System.out.println(bool);
return;
}
}
}
public void setFlag(boolean flag){
this.flag = flag;
}
}
public class Test{
public static void main(String[] args) throws InterruptedException {
MyThread mt = new MyThread();
Thread thread = new Thread(mt,"线程A");
thread.start();
Thread.sleep(200);
thread.interrupt();
System.out.println("代码结束");
}
}
6、线程优先级的设置与取得
线程优先级越高越有可能先执行,但只是可能
设置优先级:public final void setPriority(int newPriority)
取得优先级:public final int getPriority()
设置优先级的几个等级
- 最高优先级:public final static int MAX_PRIORITY = 10;
- 中等优先级:public final static int NORM_PRIORITY = 5;
- 最低优先级:public final static int MIN_PRIORITY = 1;
//设置优先级
class MyThread implements Runnable{
@Override
public void run() {
for(int i = 0; i < 5; i++){
System.out.println("当前线程名称"+Thread.currentThread().getName()+" ,i = "+i);
}
}
}
public class Test {
public static void main(String[] args) {
MyThread mt = new MyThread();
Thread thread1 = new Thread(mt,"线程1");
Thread thread2 = new Thread(mt,"线程2");
Thread thread3 = new Thread(mt,"线程3");
thread1.setPriority(Thread.MIN_PRIORITY);//设置优先级
thread2.setPriority(Thread.MAX_PRIORITY);
thread3.setPriority(Thread.MIN_PRIORITY);
thread1.start();
thread2.start();
thread3.start();
}
}
//取得主线程的优先级
public class Test {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getPriority());
//主线程的优先级为中等优先级:5
}
}
7、守护线程
Java中有两种线程:守护线程和用户线程
守护线程是一种特殊的线程,它属于是一种陪伴线程,只要当前JVM进程中存在任何一个非守护线程没有结束,守护线程就在工作;只有当最后一个非守护线程结束时,守护线程才会随着JVM一同停止工作。
可以通过isDaemon()方法来区别它们:如果返回false,则说明该线程是“用户线程”;否则就是“守护线程”。典型的守护线程就是垃圾回收线程。
//观察守护线程
class MyThread implements Runnable {
private int i;
@Override
public void run() {
try {
while (true) {
i++;
System.out.println("线程名称:" + Thread.currentThread().getName() + ",i=" + i +
",是否为守护线程:"
+ Thread.currentThread().isDaemon());
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("线程名称:" + Thread.currentThread().getName() + "中断线程了");
}
}
}
public class Test {
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new MyThread(),"子线程A");
// 设置线程A为守护线程,此语句必须在start方法之前执行
thread1.setDaemon(true);
thread1.start();
Thread thread2 = new Thread(new MyThread(),"子线程B");
thread2.start();
Thread.sleep(3000);
// 中断非守护线程
thread2.interrupt();
Thread.sleep(10000);
System.out.println("代码结束");
}
}