多线程的创建


  Java多线程,主要有三种创建模式:通过继承Thread类;通过实现Runnable接口;通过实现Callable接口。

  由于Java的单继承、多实现性,推荐多使用实现接口的方式。

继承Thread类

  通过继承Thread类,并重写run()方法,将线程中需要执行的代码内容写在run()方法中。

  在通过实例化对象的start()方法,使线程进入就绪状态。注意,不是调用run()方法,直接调用run()方法则是在单个线程中执行,并没有启用新线程,新线程的启用是在start()中实现的。

  实例:

public class Test extends Thread{//继承Thread
	
	@Override
	public void run() {
		for(int i=0;i<5;i++) {
			try {
				Thread.sleep(100); //run()方法中,不能throws异常,只能进行捕获处理
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println("听歌");
		}
	}

	public static void main(String[] args) throws InterruptedException {
		//创建子类对象,新建状态
		Test t =new Test();
		//启动,就绪状态
		t.start(); //父类Thread的方法,等待cpu调度器调用
		
		for(int i=0;i<5;i++) {
			Thread.sleep(100);
			System.out.println("在CSND写笔记"); //在main线程中进行
		}
	}
}
--------------------------------------------------
输出结果为:
听歌
在CSND写笔记
在CSND写笔记
听歌
听歌
...

实现Runnable接口

  通过继承Runnable接口,并重写run()方法,将线程中需要执行的代码内容写在run()方法中。

  此种创建模式,多线程类并没有获得Thread类的start()方法。这时需要通过新建Thread类,将多线程对象丢入构造器种,并且可以同时为线程命名(可查看Thread构造器源码了解),然后再使用新建Thread类的start()方法来启用新线程。

  实例:

public class Test implements Runnable{//实现Runnable
	
	@Override
	public void run() {
		for(int i=0;i<5;i++) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {//run()方法中,不能throws异常,只能进行捕获处理
				e.printStackTrace();
			}
			System.out.println("线程:"+Thread.currentThread().getName()+" 在听歌");
		}
	}

	public static void main(String[] args) throws InterruptedException {
		
//		Test t =new Test();  实例化测试类
//		Thread thread = new Thread(t); 新建Thread类
//		thread.start();//start()方法,线程就绪
		
//		new Thread(new Test()).start();//匿名处理
		
		new Thread(new Test(),"耳朵").start();//start()方法,启用新线程并就绪
		
		Thread.currentThread().setName("手");//为线程命名,此处为main线程
		for(int i=0;i<5;i++) {
			Thread.sleep(100);
			System.out.println("线程:"+Thread.currentThread().getName()+" 在CSND写笔记");//获取当前线程名
		}
	}
}
---------------------------------
输出结果为:
线程:手 在CSND写笔记
线程:耳朵 在听歌
线程:耳朵 在听歌
线程:手 在CSND写笔记
线程:耳朵 在听歌
...

实现Callable接口

  通过继承Callable接口,并重写call()方法,将线程中需要执行的代码内容写在call()方法中。与run()方法不同,call()方法是有返回值,并可以向上抛出异常的。

  此种创建模式,启用多线程时,需要借助Executors类创建线程池(pool的概念),再通过submit()方法提交执行。

  实例:

public class Test implements Callable<Boolean>{//实现Callable接口,有泛型,指定call()返回值类型

	@Override
	public Boolean call() throws Exception { //有返回值
		Thread.currentThread().setName("耳朵");
		for(int i=0;i<5;i++) {
			Thread.sleep(100);//call()方法中,可以用throws抛出异常
			System.out.println("线程:"+Thread.currentThread().getName()+" 在听歌");
		}
		return true;
	}

	public static void main(String[] args) throws ExecutionException, InterruptedException {
		
		//创建执行服务: 
		ExecutorService ser = Executors.newFixedThreadPool(3);
		//提交执行: 
		Future<Boolean> result =ser.submit(new Test()) ;
		
		Thread.currentThread().setName("手");
		for(int i=0;i<5;i++) {
			Thread.sleep(100);
			System.out.println("线程:"+Thread.currentThread().getName()+" 在CSND写笔记");
		}
		
		boolean res = result.get(); //线程执行结束后才能获得结果
		System.out.println(res);
	}
}
-------------------------------------------------------
输出结果为:
线程:手 在CSND写笔记
线程:耳朵 在听歌
线程:手 在CSND写笔记
线程:耳朵 在听歌
线程:耳朵 在听歌
...
true

线程属性设置

  可以查看Thread类种,有许多get/set方法,这些方法就是用来操作线程的属性,如:设置线程名、设置优先级、置为守护线程、设置线程组等。

  线程的属性一般尽量在线程启动start()前设置。
在这里插入图片描述

线程名

  在上面的实例中以及使用到了线程名,通过setName()方法命名,通过getName()方法获取名字。

  上面实例中已有,这里不再累赘写实例。

线程优先级

  线程的优先级概念,并不代表线程的执行顺序,不是排队的概念。而是优先级高的,下次调度器选线程时被选中的概率大,反之概率小,是一种概率问题。

  线程优先级为1至10,默认优先级为5。越大优先级越高,若输入参数不再1至10,回抛异常。

  通过setPriority()方法设置优先级,通过getPriority()方法获取优先级信息。实例:

		Thread thread = new Thread(new Test(),"耳朵");
		thread.setPriority(10);//设置优先级为10
		thread.start();//start()方法,启用新线程并就绪

守护线程

  守护线程,与普通线程(默认未非守护线程)相比,主要区别就是执行完毕的时机问题:

  • 当程序中还有普通线程未执行完时,java虚拟机会持续继续执行。

  • 当程序中仅有守护线程未执行完时,java虚拟机不会理会守护线程,会直接停止。

  守护线程通过setDaemon()方法设置,通过isDaemon()方法获取信息。实例:

public class Test implements Runnable{//实现Runnable
	
	@Override
	public void run() {
		for(;true;) { //死循环,永久执行
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {//run()方法中,不能throws异常,只能进行捕获处理
				e.printStackTrace();
			}
			System.out.println("线程:"+Thread.currentThread().getName()+" 在听歌");
		}
	}

	public static void main(String[] args) throws InterruptedException {
		
		Thread thread = new Thread(new Test(),"耳朵");
		thread.setDaemon(true);//设为守护线程,可以改为false再执行对比一下
		thread.start();//start()方法,启用新线程并就绪
		
		Thread.currentThread().setName("手");//为线程命名,此处为main线程
		for(int i=0;i<5;i++) {
			Thread.sleep(100);
			System.out.println("线程:"+Thread.currentThread().getName()+" 在CSND写笔记");//获取当前线程名
		}
	}
}

  虽然线程中写了死循环,但设置线程为守护线程,当其他线程都执行结束后,守护线程也会被终止,而不是永远执行下去。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Duilib 是一个基于 C++ 的 UI 框架,支持多线程创建。在 Duilib 中,使用多线程创建 UI 界面可以提高程序的响应速度,增强用户体验。下面是一个简单的多线程创建 UI 界面的示例代码: ```c++ #include "stdafx.h" #include <Windows.h> #include "DuiLib/UIlib.h" using namespace DuiLib; class CMainFrame : public WindowImplBase { public: CMainFrame() {} virtual ~CMainFrame() {} virtual CDuiString GetSkinFolder() { return _T("skin"); } virtual CDuiString GetSkinFile() { return _T("MainWnd.xml"); } virtual LPCTSTR GetWindowClassName(void) const { return _T("DUIMainFrame"); } virtual LRESULT HandleCustomMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { if (uMsg == WM_CREATE) { // 创建子线程 HANDLE hThread = CreateThread(NULL, 0, ThreadProc, this, 0, NULL); CloseHandle(hThread); } return 0; } static DWORD WINAPI ThreadProc(LPVOID lpParameter) { CMainFrame* pThis = (CMainFrame*)lpParameter; // 在子线程中创建 UI 界面 pThis->Create(NULL, _T("Duilib 多线程创建示例"), WS_OVERLAPPEDWINDOW, WS_EX_WINDOWEDGE); pThis->ShowWindow(true); pThis->CenterWindow(); return 0; } }; int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { CPaintManagerUI::SetInstance(hInstance); CMainFrame mainFrame; mainFrame.Create(NULL, _T("Duilib 多线程创建示例"), UI_WNDSTYLE_FRAME, WS_EX_WINDOWEDGE); mainFrame.CenterWindow(); mainFrame.ShowWindow(true); CPaintManagerUI::MessageLoop(); return 0; } ``` 在上述代码中,我们在主线程中创建了一个 `CMainFrame` 对象,并调用了 `Create` 方法创建了主窗口。在主窗口的 `HandleCustomMessage` 方法中,我们调用了 `CreateThread` 函数创建了一个子线程,并在子线程中调用了 `Create` 方法创建了一个 UI 界面。这样,我们就实现了在多线程创建 UI 界面的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值