35-多线程深入话题

多线程深入话题

优雅的停止线程

  多线程操作中如果要启动多线程肯定使用Thread类中的start()方法,而对于多线程需要进行停止处理,Thread类原本提供有stop()方法,但是从JDK1.2开始已经废除,除了stop()之外,还有几个方法如

  • 停止多线程:public void stop();
  • 销毁多线程:public void destory();
  • 挂起线程(暂停执行):public final void suspend();
  • 恢复挂起的线程执行:public final void resunme();

之所以费除掉这些方法,主要是这些方法有可能导致线程的死锁,所以从JDK1.2开始不建议使用。
  此时想要实现线程停止需要通过一种柔和的方式进行。
优雅的停止线程

public class ThreadStop {
    
    
	public static boolean flag = true;
	public static void main(String[] args) throws Exception {
    
    
		new Thread(()->{
    
    
			long num = 0;
			while(flag) {
    
    
				try {
    
    
					Thread.sleep(500);
				} catch (InterruptedException e) {
    
    
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() +"is running - " + num++);
			}
		},"执行线程").start();
		Thread.sleep(2000);
		flag = false;		//停止线程
	}
}

万一现在有其他线程去控制这个flag内容,那么此时对于线程的停止也不是说停就立刻停止的,而是在执行中判断flag的内容来完成。

后台守护进程

  假设有一个人且有一个保镖,那么这个保镖是在这个人活着的时候进行守护,如果这个人已经死了,那么保镖无用。所以在多线程中可以进行守护线程的定义,也就是说如果现在主线程的程序或其他线程还在执行的时候,那么守护线程将一直存在,并且运行在后台状态。
Thread类中提供有如下守护进程的方法:

  • 设置为守护线程:public final void setDaemon(boolean on);
  • 判断是否为守护线程:public final boolean isDaeon();

守护线程

public class ThreadStop {
    
    
	public static boolean flag = true;
	public static void main(String[] args) throws Exception {
    
    
		Thread userThread = new Thread(()->{
    
    
			for(int x=0; x<10; x++) {
    
    
				try {
    
    
					Thread.sleep(100);
				} catch (InterruptedException e) {
    
    
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() +"is running - x=" + x);
			}
		},"用户线程"); 		//完成核心业务
		Thread daemonThread = new Thread(()->{
    
    
			for(int x=0; x<Integer.MAX_VALUE; x++) {
    
    
				try {
    
    
					Thread.sleep(100);
				} catch (InterruptedException e) {
    
    
					e.printStackTrace();
				}
				System.out.println(Thread.currentThread().getName() +"is running - x=" + x);
			}
		},"守护线程"); 		
		daemonThread.setDaemon(true);		//设为守护线程
		userThread.start();
		daemonThread.start();
	}
}

守护线程是围绕在用户线程周围,如果程序执行完毕了,守护线程也就消失了,在整个JVM中最大的守护线程就是GC线程。
  程序执行中GC线程会一直存在,如果程序执行完毕,GC线程也将消失。

volatile关键字

  在多线程定义中,volatile关键字主要是在属性定义上使用的,表示此属性为直接进行数据操作,而不进行副本的拷贝处理。在一些书上就将其错误的理解为同步属性。
在正常进行变量处理的时候往往会经历如下几个步骤:

  1. 获取变量原有的数据内容;
  2. 利用副本为变量进行数学计算;
  3. 将计算后的变量,保存到原始空间之中;

而如果一个属性追加了volatile关键字,表示不适用副本,而是直接操作原始变量,相当于节约了拷贝副本、重新保存的步骤。
r3yu0f.png

class MyThreadTic implements Runnable{
    
    
	private volatile int ticket = 10; 	//直接内存操作
	public synchronized boolean sale() {
    
    
		if(this.ticket > 0) {
    
    
			try {
    
    
				Thread.sleep(100);
			} catch (InterruptedException e) {
    
    
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "买票,ticket="+ this.ticket--);
			return true;
		} else {
    
    
			System.out.println("票已卖完!");
			return false;
		}
	}
	@Override
	public void run() {
    
    
		while (this.sale()) {
    
    
			;
		}
	}
}
public class TicketDemo {
    
    
	public static void main(String[] args) {
    
    
		MyThreadTic mt = new MyThreadTic();
		new Thread(mt, "票贩子A").start();
		new Thread(mt, "票贩子B").start();
		new Thread(mt, "票贩子C").start();
	}
}

面试 解释volatile和synchronized的区别?

  • volatile主要在属性上使用,而synchronized是在代码块与方法上进行使用;
  • volatile无法描述同步处理,只是一种直接内存的处理,避免了副本的操作,而synchronized是实现同步的。
    ed的区别?
  • volatile主要在属性上使用,而synchronized是在代码块与方法上进行使用;
  • volatile无法描述同步处理,只是一种直接内存的处理,避免了副本的操作,而synchronized是实现同步的。

猜你喜欢

转载自blog.csdn.net/MARVEL_3000/article/details/111567500