Java笔记——多线程总结

创建线程的三种方式

	public class MyThread extends Thread
	{
		@Override
		public void run()
		{
		}
	}
	new MyThread().start();
		new Thread(new Runnable()
		{
			@Override
			public void run()
			{
			}
		}).start();
		FutureTask<String> task = new FutureTask<String>(new Callable<String>()
		{
			@Override
			public String call() throws Exception
			{
				return null;
			}
		});
		new Thread(task).start();
		try
		{
			String result = task.get(); // 阻塞式取值
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		catch (ExecutionException e)
		{
			e.printStackTrace();
		}

线程常用方法

thread.isAlive(); // 判断线程是否活动(是否已经start并且尚未结束)
thread.join(); // 当前线程会等待thread执行返回
thread.setDaemon(true); // 设置为后台线程(当只有后台线程时,进程会结束)
thread.setPriority(Thread.MAX_PRIORITY); // 优先级
Thread.yield(); // 暂停一下

两种线程同步方式

  • 同步监视器

同步监视器 synchronized 同步代码块、同步方法
sleep、yield 不会释放同步锁
wait 会释放同步锁(wait需要synchronized括号里的那个东西来调用,它是一个Object方法)
wait、notify、notifyAll

  • 同步锁(ReentrantLock、ReentrantReadWriteLock)

简单用法:

	private final ReentrantLock lock = new ReentrantLock();
	
	public void dosomething()
	{
		lock.lock(); // tryLock、lockInterruptibly
		try
		{
			// TODO
		}
		finally
		{
			lock.unlock();
		}
	}

带条件用法:

	private final ReentrantLock lock = new ReentrantLock();
	private final Condition condition = lock.newCondition();

	public void dosomething()
	{
		lock.lock();
		try
		{
			if (true) // 根据业务替换其它条件
			{
				condition.await();
			}
			else
			{
				condition.signalAll();
			}
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		finally
		{
			lock.unlock();
		}
	}

阻塞队列(BlockingQueue)

阻塞队列(BlockingQueue)可用于一个线程存,一个线程取的情况

常用实现类:

ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(2);

线程组 ThreadGroup 用于管理线程,它可以是个树组合(因为有getParent方法)

常用方法

        threadGroup.activeCount();
        threadGroup.interrupt();
        threadGroup.isDaemon();
        threadGroup.setDaemon(true);

线程池常规用法

		ExecutorService pool = Executors.newFixedThreadPool(5);
		pool.execute(new Runnable()
		{
			@Override
			public void run()
			{
			}
		});
		Future<String> result = pool.submit(new Callable<String>()
		{
			@Override
			public String call() throws Exception
			{
				return null;
			}
		});
		try
		{
			if (result.isDone())
				result.get();
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		catch (ExecutionException e)
		{
			e.printStackTrace();
		}
		pool.shutdown();

其它线程池

        Executors.newCachedThreadPool();
        Executors.newFixedThreadPool(5);
        Executors.newSingleThreadExecutor();

        Executors.newScheduledThreadPool(5);
        Executors.newSingleThreadScheduledExecutor();

        Executors.newWorkStealingPool(Runtime.getRuntime().availableProcessors());
        Executors.newWorkStealingPool();

ThreadPoolExecutor

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

int corePoolSize : 核心线程数

int maximumPoolSize : 最大线程数

long keepAliveTime, TimeUnit unit : 非核心线程闲置的超时时间(超时将被回收)

    executor.allowCoreThreadTimeOut(true); // 可将超时同时作用到核心线程

BlockingQueue<Runnable> workQueue : 任务队列

ThreadFactory threadFactory : 线程工厂

RejectedExecutionHandler handler : 饱和策略

    new ThreadPoolExecutor.AbortPolicy(); // 抛出异常(默认)
    new ThreadPoolExecutor.CallerRunsPolicy(); // 用调用者所在线程处理
    new ThreadPoolExecutor.DiscardPolicy(); // 丢弃新任务
    new ThreadPoolExecutor.DiscardOldestPolicy(); // 挤掉一个任务

示例用法

	private static final ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 50, 5, TimeUnit.SECONDS, 
			new ArrayBlockingQueue(5), new ThreadPoolExecutor.DiscardOldestPolicy());

线程池默认是空的(可调用 prestartAllCoreThreads 提前启动核心线程),若持续有任务进来,会先填满 5 个核心线程,然后进任务队列,任务队列满了,会继续创建线程直到 50 个,再然后会执行饱和策略

ForkJoinPool 用于分解任务

一般用法

	public class PrintTask extends RecursiveAction
	{
		private int start, end;

		public PrintTask(int start, int end)
		{
			this.start = start;
			this.end = end;
		}

		@Override
		protected void compute()
		{
			if (end - start < 50)
			{
				for (int i = start; i < end; i++)
				{
					LOG.v(Thread.currentThread().getName() + " - " + i);
				}
			}
			else
			{
				int middle = (start + end) / 2;
				PrintTask left = new PrintTask(start, middle);
				PrintTask right = new PrintTask(middle, end);
				left.fork();
				right.fork();
			}
		}
	}

调用示例
		ForkJoinPool pool = new ForkJoinPool();
		pool.submit(new PrintTask(0, 300));
		pool.shutdown();

带返回值的用法

	public class PrintTask extends RecursiveTask<Integer>
	{
		private int start, end;

		public PrintTask(int start, int end)
		{
			this.start = start;
			this.end = end;
		}

		@Override
		protected Integer compute()
		{
			int sum = 0;
			if (end - start < 50)
			{
				for (int i = start; i < end; i++)
				{
					sum += i;
				}
			}
			else
			{
				int middle = (start + end) / 2;
				PrintTask left = new PrintTask(start, middle);
				PrintTask right = new PrintTask(middle, end);
				left.fork();
				right.fork();
				sum = left.join() + right.join();
			}
			return sum;
		}
	}

调用示例
		ForkJoinPool pool = new ForkJoinPool();
		ForkJoinTask<Integer> result = pool.submit(new PrintTask(0, 300));
		try
		{
			LOG.v("result : " + result.get());
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		catch (ExecutionException e)
		{
			e.printStackTrace();
		}
		pool.shutdown();

ThreadLocal 用于为每个线程生成数据副本

	private ThreadLocal<String> data = new ThreadLocal<>();

	public void func()
	{
		data.get();
		data.set("some");
	}

将集合包装为线程安全系列方法

Collections.synchronizedXxx()

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值