JAVA学习第二十八课(多线程(七))- 停止线程和多线程面试题

重点掌握

/*

* wait 和 sleep 区别?

* 1.wait可以指定时间也可以不指定

* sleep必须指定时间

* 2.在同步中,对CPU的执行权和锁的处理不同

* wait释放执行权,释放锁    sleep释放执行权,不释放锁

*/

//同步里具备执行资格的线程不止一个,但是能得到锁的只有一个,所以能执行的也只有一个

一、停止线程的方式

不可能让线程一直在运行,所以需要让线程停止

1.定义循环结束标记

一般而言,线程运行代码都是循环的,只要控制了循环就可以结束任务

2.使用interrupt(中断)

结束线程的冻结状态,使线程回到运行状态

PS:stop过时了,不用了

第一种方式:(常用)

class StopThread implements Runnable
{
	private boolean flag = true;
	public void run()
	{
		while(flag)
		{
			System.out.println(Thread.currentThread().getName()+"---");
		}
	}
	public void ChangeFlag()
	{
		flag = false;
	}
}
public class Main
{
	public static void main(String[] args)
	{
		StopThread s = new StopThread();
		Thread t1 = new Thread(s);
		Thread t2 = new Thread(s);
		t1.start(); t2.start();
		int i = 0;
		while(true)
		{
			if(++i == 20)//i达到20后结束所有线程
			{
				s.ChangeFlag();
				break;
			}
			System.out.println("Main.main"+i);
		}
			System.out.println("Final");
	}
}

缺点:

class StopThread implements Runnable
{
	private boolean flag = true;
	public synchronized void run()
	{
		while(flag)
		{
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO: handle exception
				System.out.println(Thread.currentThread().getName()+"..."+e);
			}
			System.out.println(Thread.currentThread().getName()+"-++--");
		}
	}
	public void ChangeFlag()
	{
		flag = false;
	}
}

主线程结束了,t0 t1直接wait()了,如果线程处于了冻结状态,就无法读取标记,所以就引入了第二种结束线程的方式

第二种方式:interrupt

将线程从冻结状态强制恢复到运行状态中,使线程回到具备CPU执行资格的状态,但是会发生中断异常(InterruptException)

class StopThread implements Runnable
{
	private boolean flag = true;
	public synchronized void run()
	{
		while(flag)
		{
			try {
				wait();
			} catch (InterruptedException e) {
				// TODO: handle exception
				System.out.println(Thread.currentThread().getName()+"........."+e);
				flag = false;//注意处理,不加这个会导致线程继续等待,主线程结束t1 t2未结束
			}
			System.out.println(Thread.currentThread().getName()+"-++--");
		}
	}
	public void ChangeFlag()
	{
		flag = false;
	}
}
public class Main
{
	public static void main(String[] args)
	{
		StopThread s = new StopThread();
		Thread t1 = new Thread(s);
		Thread t2 = new Thread(s);
		t1.start(); t2.start();
		int i = 0;
		while(true)
		{
			if(++i == 20)//i达到20后结束所有线程
			{
				//s.ChangeFlag();
				t1.interrupt();
				t2.interrupt();
				break;
			}
			System.out.println("Main.main"+i);
		}
			System.out.println("Final");
	}
}

二、守护线程

setDaemon(boolean)

public class Main
{
	public static void main(String[] args)
	{
		StopThread s = new StopThread();
		Thread t1 = new Thread(s);
		Thread t2 = new Thread(s);
		t1.start();
		t2.setDaemon(true);//守护线程,可以理解为后天线程
		//后天线程的特点:运行和前台线程一样,和CPU抢夺执行权
		//           结束:前台线程必须手动结束,后台线程如果所有的前提线程都结束了,后台线程也跟着结束
		t2.start();
		int i = 0;
		while(true)
		{
			if(++i == 20)//i达到20后结束所有线程
			{
				//s.ChangeFlag();
				t1.interrupt();
				//t2.interrupt();
				break;
			}

			System.out.println("Main.main"+i);
		}
			System.out.println("Final");
	}
}

守护线程简单理解:比如说(英雄联盟)LOL,我方英雄需要守护我方的防御塔,塔没了,守护线程也就没必要存在了

三、线程的其他方法

1.join()

2.setPriority()

class Demo implements Runnable
{
	public void run()
	{
		for(int i = 0;i<20;i++)
			System.out.println(Thread.currentThread().getName()+"..."+i);
	}
}

public class Main
{
	public static void main(String[] args)throws Exception
	{
		Demo d = new Demo();
		Thread t1 = new Thread(d);
		Thread t2 = new Thread(d);
		t1.start();
		t1.join();//t1线程要申请加入进来,运行,也就是t1不完,t2 和 主线程 就不能执行,
		//临时假如一个线程,就要用join方法
		t2.start();//如果join放在t2.start()后面,那么主线程只等待t1完成后运行,而t1和t2互相争夺执行权
		for(int i = 0;i<20;i++)
			System.out.println(Thread.currentThread().getName()+".."+i);
	}
}

优先级:setPriority

class Demo implements Runnable
{
	public void run()
	{
		for(int i = 0;i<20;i++)
			System.out.println(Thread.currentThread().toString()+"..."+i);
	}
}

public class Main
{

	public static void main(String[] args)throws Exception
	{
		Demo d = new Demo();

		Thread t1 = new Thread(d);
		Thread t2 = new Thread(d);
		t1.start();
		t2.start();
		t2.setPriority(Thread.MAX_PRIORITY);
		// Thread.MIN_PRIORITY优先级最小1
		//Thread.MAX_PRIORITY 有效级最大10
		//Thread.NORM_PRIORITY 默认优先级 5
		for(int i = 0;i<20;i++)
			System.out.println(Thread.currentThread()+".."+i);
	}
}

3.线程组

把10个线程放一个组里,如果中断这一组线程,那么这10个线程都中断了

4.yield()暂停当前正在执行的线程,并执行其他线程

class Demo implements Runnable
{
	public void run()
	{
		for(int i = 0;i<20;i++)
			{
			System.out.println(Thread.currentThread().toString()+"..."+i);
		Thread.yield();
			}
	}
}
public class Main
{

	public static void main(String[] args)throws Exception
	{
		new Thread()//线程子类
		{
			public void run()
			{
				for(int i = 0;i<20;i++)
				{
				 System.out.println(Thread.currentThread().getName()+"x = "+i);
				}
			}
		}.start();

		for(int i = 0;i<20;i++)
		{
		 System.out.println(Thread.currentThread().getName()+"y = "+i);
		}
		Runnable r = new Runnable()
		{
			public void run()
			{
				for(int i = 0;i<20;i++)
				{
				 System.out.println(Thread.currentThread().getName()+"z = "+i);
				}
			}
		};
		new Thread(r).start();
	}
}

多线程面试题:

1.

class Text implements Runnable
{
	public void run(Thread t)
	{

	}
}
//是否编译失败?如果失败错误在哪?

失败,没有实现run方法的覆盖

改法一:

abstract class Text implements Runnable
{
	public void run(Thread t)
	{

	}
}

改法二:重载,进行覆盖

class Text implements Runnable
{
	public void run()
	{
		System.out.println("Text.run()1");
	}
	public void run(Thread t)
	{
		System.out.println("Text.run()2");
	}
}

2.

public class Main
{

	public static void main(String[] args)throws Exception
	{

		new Thread(new Runnable()
		{
			public void run() {
				// TODO Auto-generated method stub
				System.out.println("Runnable run");
			}
		})
		{
			public void run()
			{
				System.out.println("Thread run");
			}
		}.start();//这段代码编译能通过吗?如果能打印哪一句
	}
}

打印Thread run

以子类为主,没有子类以父类为主

时间: 2024-10-14 19:49:15

JAVA学习第二十八课(多线程(七))- 停止线程和多线程面试题的相关文章

JAVA学习第二十八课(常用对象API)- String类

多线程告一段落,开始常用对象API的涉及,背也要背下来!!! 日后开发,遇见最多的对象是文字,也就是字符串 String类 字符串是一个特殊对象 字符串一旦初始化就不可以被改变 一.特点 public class Main { public static void main(String[] args) { Demo1(); System.out.println("--------------"); Demo2(); } /*演示字符串的第一种定义方式,并明确字符串常量池的特点*/ p

JAVA学习第二十四课(多线程(三))- 线程的同步

继续以卖票为例 一.线程安全问题的解决 同步的第一种表现形式:同步代码块 思路: 将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程是不允许参与运算的,必须要当期线程把代码执行完毕后,其他线程才可以参与运算 在java中用同步代码块解决这个问题 同步代码块格式: synchronized(对象) { 需要被同步的代码部分 } class Ticket implements Runnable { private int num = 100; Object god = ne

JAVA学习第二十二课(多线程(二))- (多线程的创建方式一 :继承Thread类)

线程是程序中的执行线程.Java 虚拟机允许应用程序并发地运行多个执行线程. 创建新执行线程有两种方法. 一种方法是将类声明为 Thread 的子类.该子类应重写Thread 类的run 方法.另一种方法是声明实现 Runnable 接口的类.该类然后实现run 方法. 创建线程方式一:继承Thread类 一.创建线程的步骤: 1.定义一个类继承Thread类 2.覆盖Thread中的run()方法 3.直接创建Thread类子类的对象 4.调用start方法开启线程,并调用线程的任务run方法

JAVA学习第二十六课(多线程(六))- 多生产者多消费者问题

多生产者多消费者问题 以生产馒头 消费馒头为例. class Resource { private String name; private int count = 1; private boolean flag = false; public synchronized void set(String name) { if (flag) { try { this.wait(); } catch (Exception e) { // TODO: handle exception } } this.

JAVA学习第二十五课(多线程(四))- 单例设计模式涉及的多线程问题

一.多线程下的单例设计模式 利用双重判断的形式解决懒汉式的安全问题和效率问题 //饿汉式 /*class Single { private static final Single t = new Single(); private Single(){} public static Single getInstance() { return t; } } */ //懒汉式 class Single { private static Single t = null; private Single()

JAVA学习第二十六课(多线程(五))- 多线程间的通信问题

一.线程间的通信 实例代码: 需求是:输入一个姓名和性别后,就输出一个姓名和性别 class Resource { String name; String sex ; } class Input implements Runnable { Resource r; Input(Resource r) { this.r = r; } public void run() { int x = 0; while(true) { synchronized (r) { if(x==0) { r.name =

JAVA学习第二十九课(经常使用对象API)- String类

多线程告一段落,開始经常使用对象API的涉及,背也要背下来!.! 日后开发,遇见最多的对象是文字,也就是字符串 String类 字符串是一个特殊对象 字符串一旦初始化就不能够被改变 一.特点 public class Main { public static void main(String[] args) { Demo1(); System.out.println("--------------"); Demo2(); } /*演示字符串的第一种定义方式,并明白字符串常量池的特点*/

JAVA学习第十八课(异常及其思想 (一) )

异常:重要知识点 异常处理的代码简单,重要还是理解其思想 一.概述: 异常就是在运行时发生的不正常情况 Throwable: Error 通常出现重大问题如,运行的类不存在或者内存溢出等 不编写针对代码对其处理 Exception 在运行时运行出现的一起情况,可以通过trt catch finally Exception和Error的子类名都是以父类名作为后缀 异常举例:数组越界.传递参数错误啊... class Futime { } class Bigtime { } public class

NeHe OpenGL教程 第二十八课:贝塞尔曲面

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第二十八课:贝塞尔曲面 贝塞尔曲面: 这是一课关于数学运算的,没有别的内容了.来,有信心就看看它吧. 贝塞尔曲面 作者: David Nikdel ( [email protected] ) 这篇教程旨在介绍贝塞尔曲面,希望有比我更