启动线程和关闭线程

前段时间面试被问到启动线程的方法,经常用的就是继承Thread,重写它的run()方法,或者是实现runnable接口,然后被问到还有没有别的方法时,就懵了。今天就是要记录下来。

一、启动线程

1.继承Thread,重写run()方法。

	 public static void main(String args[]) {
		 MyThread myThread = new MyThread();
		 myThread.start();
		 MyThread myThread2 = new MyThread("A");
		 myThread2.start();
		 System.out.println("qqqq");
	}
	 static class MyThread extends Thread{
		 private String str;
		 public MyThread() {
			// TODO Auto-generated constructor stub
			 super();
		}
		 public MyThread(String str){
			 this.str = str;
		 }
		 @Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			for(int i = 0;i<3;i++){
				System.out.println(str+"     "+i);
			}
		}
	 }

重写run()方法后,调用start()方法。

为什么调用start()方法,而不是run()呢?

多线程就是好多线程在排队等着cpu,调用start()方法,就是让线程进入等待的队列,执行接下来的代码。什么时候轮到使用cpu,什么时候run()方法就会被调用。直接调用run()方法,线程就要等着run()方法执行结束了,才会执行接下来的代码。

上述代码段两个线程都是被start的,执行结果就会出现多种情况。(列出几个例子,并不是全部)

           

如果上述代码中;两个线程都是被run的,执行结果只有一种。

从多线程的角度考虑,调用start()才是真正的多线程。

2.实现runnable接口

	 public static void main(String args[]) {
		 MyRunable myRunable = new MyRunable("B");
		 Thread thread = new Thread(myRunable);
		 thread.start();
	}
	 
	 static class MyRunable implements Runnable{
		 String string;
		 public MyRunable(String str) {
			// TODO Auto-generated constructor stub
			 string = str;
		}

		@Override
		public void run() {
			// TODO Auto-generated method stub
			for(int i = 0;i<3;i++){
				System.out.println(string+"    "+i);
			}
		}
		 
	 }

运行结果如下:

这两种有什么区别呢?

	 public static void main(String args[]) {
		 MyRunable myRunable = new MyRunable();
		 Thread thread = new Thread(myRunable,"AA");
		 thread.start();
		 
		 Thread thread1 = new Thread(myRunable,"BB");
		 thread1.start();
	}
	 
	 static class MyRunable implements Runnable{
		 int num = 10;;

		@Override
		public void run() {
			// TODO Auto-generated method stub
			for(int i = 0;i<10;i++){
				if(num>0){
					System.out.println(Thread.currentThread().getName()+"    "+num--);
				}
				
			}
		}
		 
	 }

运行结果

区别就是继承线程,每个线程都是独立的,就不能实现上面代码的效果。实现runnable接口实现线程可以共用runnable,实现上述功能。如果想实现线程独立,不共用runnable就可以了。

还有就是java里面不支持多继承问题,用runnable就可以很好的解决这个问题。

3.FutureTask和Callable

	 public static void main(String args[]) {
		 Mycallable mycallable = new Mycallable(1, 2);
		 FutureTask<Integer> task = new FutureTask<Integer>(mycallable);
		 Thread thread = new Thread(task);
		 thread.start();
		 try {
			int sum = task.get();
			System.out.println(sum);
		} catch (InterruptedException | ExecutionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	 static class Mycallable implements Callable<Integer>{

		 private int m;
		 private int n;
		 Mycallable(Integer a,Integer b){
			 m = a;
			 n = b;
		 }
		@Override
		public Integer call() throws Exception {
			// TODO Auto-generated method stub
			int sum = m+n;
			return sum;
		}
		 
	 }

与runnable相比,可以获取返回值,也可以捕获一些异常。

4.匿名内部类

这种用的也挺多的,但是一直没有归为一类。这次总结上。

	 public static void main(String args[]) {
		 MyThread myThread = new MyThread();
		 new Thread().start();
		 new MyThread("AA").start();
		 new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				for(int i = 0;i<3;i++){
					System.out.println(i);
				}
			}
		}).start();
	}

二、停止一个线程

1.stop

开启一个线程,不管用什么方法,最终都要调用start方法,那么终止一个线程stop就可以了吗?

stop这个方法已经废止了,说是不安全。我理解的是,stop可以使一个正在运行的线程终止,正在运行的线程突然终止,可能是一些资源来不及释放,或者是占用的一些锁来不及解锁。

2.添加退出的条件。

比如在run方法中添加结束的条件。

	 static class MyThread extends Thread{
		 private String str;
		 private int num;
		 public MyThread() {
			// TODO Auto-generated constructor stub
			 super();
		}
		 public MyThread(String str){
			 this.str = str;
		 }
		 @Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			while(num<10){
				System.out.println(str+"     "+num);
				num++;
			}
		}
	 }

3.interrupt

	 public static void main(String args[]) {
		 MyThread myThread = new MyThread("AA");
		 myThread.start();
		 try {
			myThread.sleep(20);
			myThread.interrupt();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	 static class MyThread extends Thread{
		 private String str;
		 private int num;
		 public MyThread() {
			// TODO Auto-generated constructor stub
			 super();
		}
		 public MyThread(String str){
			 this.str = str;
		 }
		 @Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			for(int i = 0;i<50000;i++){
				System.out.println(str+"     "+i);
			}
		}
	 }

这样发现线程并没有停下来,interrupt方法,并没有让线程停下来,只是给线程加了一个停止的标志。真正的想要停下来,就有很多方法了,主要还是判断线程的状态,然后停止操作。和方法二有点类似。这里使用判断线程状态+return来实现。

	 public static void main(String args[]) {
		 MyThread myThread = new MyThread("AA");
		 myThread.start();
		 try {
			myThread.sleep(20);
			 myThread.interrupt();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	 static class MyThread extends Thread{
		 private String str;
		 private int num;
		 public MyThread() {
			// TODO Auto-generated constructor stub
			 super();
		}
		 public MyThread(String str){
			 this.str = str;
		 }
		 @Override
		public void run() {
			// TODO Auto-generated method stub
			super.run();
			for(int i = 0;i<50000;i++){
				if(isInterrupted()){
					return;
				}
				System.out.println(str+"     "+i);
			}
		}
	 }

在MFC中,使用`AfxBeginThread`是一个更高级别的API来创建并开始新线程,它会自动管理线程的生命周期。下面是如何通过`AfxBeginThread`启动关闭线程的一个例子: ```cpp // 创建线程函数 DWORD WINAPI MyThreadProc(LPVOID lpParam) { // 这里是你想要线程执行的任务 // ... return 0; // 返回值通常表示线程结束时的状态 } // 开启线程 void StartNewThread() { DWORD dwThreadId; // 使用AfxBeginThread创建新的工作线程,并传递自定义线程函数的地址 AfxBeginThread(MyThreadProc, NULL, &dwThreadId, THREAD_PRIORITY_NORMAL, CREATE_SUSPENDED, NULL); // 线程可能还没开始运行,所以这里可以先做其他事情 // 启动线程(如果需要) ResumeThread(dwThreadId); // 如果你想让线程立即开始执行 } // 关闭线程 void CloseThread() { if (IsThreadRunning()) { // 判断线程是否还在运行 // 你可以选择优雅的方式,如设置标志,然后等待线程退出 bool bTerminated = false; SetThreadTerminateFlag(&bTerminated); // 设置一个终止标志 while (!bTerminated && IsThreadRunning()) { Sleep(100); // 每隔一段时间检查一下线程状态 } // 如果线程尚未退出,强制结束 if (!bTerminated) TerminateThread(GetCurrentThread(), -1); // 使用默认错误码-1强制结束 } } ``` 在上面的例子中,线程在`MyThreadProc`中执行,`StartNewThread`首先创建线程但保持其暂停,然后在适当的时候调用`ResumeThread`启动它。关闭线程时,我们首先检查线程是否运行,然后可以选择等它自然结束(通过设置终止标志),或者强制结束。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值