多线程基础学习记录


一、多线程实现方式

1.1 无返回值

1.1.1 继承Thread类

代码如下(示例):

public class TheadDemo extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(super.getName() + "==>" + i);
		}
	}

	public static void main(String[] args) {
		new TheadDemo().start();
		new TheadDemo().start();
	}
}

1.1.2 实现Runnable接口

代码如下(示例):

public class RunnableDemo implements Runnable{
	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"==>"+i);
		}
	}
	public static void main(String[] args) {
		RunnableDemo runnableDemo=new RunnableDemo();
		new Thread(runnableDemo).start();
		new Thread(runnableDemo).start();
	}
}

1.1.3 二者的优缺点

  1. Java使用的是单继承,所以使用继承Thread类来实现多线程会无法继承其他类
  2. 使用继承方式实现线程,在启动线程时需要new一个线程的实现类,导致无法实现资源共享
  3. 使用继承方式可以直接使用Thread的一些方法,有些时候会更简便些
  4. 这两种方法在运行中都没有返回值,若需要返回值或在线程运行中需要取消线程可以考虑下面介绍的 Callable接口

启动线程请调用start()方法,而不是调用run()方法
在需要共享资源时常常使用锁来防止多消费等问题

1.2. 有返回值Callable

1.2.1 Callable简单使用

代码如下(示例):

public class CallableDemo implements Callable<Integer> {
		@Override
		public Integer call() throws Exception {
			Thread.sleep(1000);
			return 4343;
		}


		public static void main(String[] args) throws ExecutionException, InterruptedException {
			ExecutorService executor = Executors.newCachedThreadPool();
			CallableDemo task = new CallableDemo();
			Future<Integer> result = executor.submit(task);
			// 注意调用get方法会阻塞当前线程,直到得到结果。
			// 所以实际编码中建议使用可以设置超时时间的重载get方法。
			System.out.println(result.get());
			executor.shutdown();
		}
	}

1.2.2 Future接口常用方法介绍

代码如下(示例):

	//尝试取消一个线程的执行,不一定会成功。例如线程已执行完成、线程已取消、或其他因素导致取消失败。
	boolean cancel(boolean mayInterruptIfRunning);

	// 线程是否已取消
	boolean isCancelled();
		
	// 线程是否已结束
	boolean isDone();
		
	// 获取返回值
	V get() throws InterruptedException, ExecutionException;
		
	// 在规定时间内获取返回值,若在时间内没获取到则报错
	V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
		

二、线程组与线程优先级的设置

2.1 线程组

	在Java中线程是存在于线程组中的,如果你在创建线程时没有指定线程组,那么系统会将你分配到父线程所在的线程组上

代码如下(示例):

public static void main(String[] args) {
	Thread testThread = new Thread(() -> {
		System.out.println("testThread当前线程组名字:" +
		Thread.currentThread().getThreadGroup().getName());
		System.out.println("testThread线程名字:" +
		Thread.currentThread().getName());
	});

	testThread.start();
	System.out.println("执行main所在线程的线程组名字: " + 	Thread.currentThread().getThreadGroup().getName());
	ystem.out.println("执行main方法线程名字:" + Thread.currentThread().getName());
}

运行结果:

执行main所在线程的线程组名字: main
testThread当前线程组名字:main
执行main方法线程名字:main
testThread线程名字:Thread-0

2.2 线程优先级设置

  1. 在Java中线程优先级分为1-10 ,默认为5,优先级越高越有可能抢到资源,获得交配权。
  2. 使用Thread类的setPriority()来设置线程的优先级
    注:并非优先级越高就越先执行,设置优先级就像是设置抽奖一样(当然不是腾讯的那种抽奖),优先级高的先执行的可能性比较大一点而已。并且最终解释权在操作系统手里。

三、线程的六种状态与转态之间的转换

3.1 线程的状态

public enum State {
	NEW,	
	RUNNABLE,	
	BLOCKED,
	WAITING,
	TIMED_WAITING,
	TERMINATED;
}
  1. NEW: 新建状态,在创建完线程但未执行start() 方法前,线程属于 新建状态,在创建完线程但未执行start()方法
  2. RUNNABLE:运行状态,Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
    线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)
  3. BLOCKED:阻塞状态,线程在等待锁的释放时的状态
  4. WAITING:等待状态,等待其他线程唤醒
  5. TIMED_WAITING:超时等待状态,与WAITING不同,TIMED_WAITING在时间到的时候可以自己唤醒自己
  6. TERMINATED:终止状态,线程已经执行完毕了

3.2 线程状态转化图

线程状态转化图

总结

提示:以上内容参考于 深入浅出Java多线程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值