Java线程的创建与使用

1 . 线程的创建方式
常见创建线程的4四种方式:

  1. 继承Thread类,重写run()方法,java单一继承原则,类继承Thread后无法再继承其它类,使用时需注意;
public static class Ta extends Thread{

		@Override
		public void run() {

		}
	}
  1. 实现Runable接口,实现run()方法,可以实现多个接口;
public static class Tb implements Runnable {

		@Override
		public void run() {
			
		}
	}
  1. 实现Callable接口,重写call()方法,实现Callable接口来创建的线程,可以通过FutureTask类接收线程的处理结果;
public static class Tc implements Callable<Integer> {

    @Override
    public Integer call() throws Exception {
       
    }
}
  1. 线程池(实际项目使用推荐使用该方式);
    常用线程池(4种):
    1 . newCachedThreadPool:可缓存线程池,线程池最大容量为Interger.MAX_VALUE,可线程空闲超时可自动回收,使用时要注意控制任务的数量,否则,由于大量线程同时运行会造成系统瘫痪。
    2 . newFixedThreadPool:指定工作线程数量的线程池,每当任务一提交就会创建一个工作线程,知道线程数达到线程池初始最大数。创建的线程不会自动销毁,但是可以提高效率和节省线程创建所耗开销,线程空闲会占用一定的系统资源。
    3 . newSingleThreadExecutor:创建一个单线程化的Executor,只创建唯一的工作者线程来执行任务,可保证任务按顺序执行。
    4 . newScheduleThreadPool:创建一个定长的线程池,而且支持定时的以及周期的任务执行。
    注意:创建线程池不要使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险.。因为Executors 为默认创建
    1)创建FixedThreadPool 和 SingleThreadPool的允许的请求队列长度为 Integer.MAX_VALUE,可能会堆积大量的请求,从而导致内存资源不足;
    2)创建CachedThreadPool 和 ScheduledThreadPool的允许的创建线程数量为 Integer.MAX_VALUE,可能会创建大量的线程,从而导致内存资源不足;

2. 线程的使用
当web层接收到一个请求时,就会去线程池拿一个空闲线程使用;
这个线程就成为了就绪状态,等待cpu去调用,CPU执行线程是可以在任何时候让
改线程记住当状态停止任务回到就绪状态,等待cpu再次调用,以此往复直到这个
线程的任务完成。

1 .线程加锁问题
转账业务,账户A,一个线程向A中存钱,一个线程取钱;
如果在没有对用户A加锁时,存钱取钱都是对同一个余额操作,导致结果时存完余额为
1000+300,取钱操作完后更新余额为1000-300,最后结果为700;
加锁处理流程为,存钱线程执行时,取钱线程无法获取用户A,只有等待存钱完后才能
获取用户A,因此取钱执行结果是1300-300=1000。

2 .多个资源加锁导致死锁问题
现象:有A和B两个需要加锁资源,1号线程执行A给B转账,2号线程执行B给A转账;
1线程获取A的锁,2线程获取B的锁,cpu再次执行1号线程时会再去获取B的锁这是发现
锁被使用就会等带锁B释放,同样2号线程获取A线程也会一直等待,这个时候就出现了死锁,
导致cpu利用率飙升;
解决方法:
1.顺序加锁,在1号,2号线程获取A和B锁的顺序要指定一个算法顺序,例如每次获取都是
获取资源大的锁(if A>B return A);
2.加锁时限,当线程尝试获取锁时加上一个超时时限,超过时限就放弃该锁,并释放已经
获取的锁,然后等待一段时间在重试;
3.死锁检测机制,主要针对那些不可能按顺序加锁且加锁超时不可行的场景。

3.线程并发问题解决:两个线程分别打印出二十六个字母中的元音字母和其它字母,要求按字母顺序打印;
问题场景描述:多个线程对统一个数据集做不同的任务处理,设计数据集资源的并发控制。

public class ThreadDemo{

	//共计26字母
	public static String[] words = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};

	//记录当前检索的字段下标 (用volatile 关键字修饰实现线程间的变量数据是通步的)
	public static volatile int wordsIndex = 0;

	//实现公平锁,依次交替打印26字母
	public static ReentrantLock lock = new ReentrantLock(true);

	public static void main(String[] args) throws InterruptedException {
		//创建线程One
		ThreadOne threadOne = new ThreadOne ();
		Thread threadA = new Thread(threadOne );
		//创建线程Two
		ThreadTwo threadTwo = new ThreadTwo ();
		Thread threadB = new Thread(threadTwo );
		// 启动任务
		threadA.start();
		threadB.start();
	}

	public static class ThreadOne implements Runnable {

		@Override
		public void run() {
			// 打印元音字母
			wordsIndex = 0;
			while (true){
				//阻塞100ms,避免其它线程还未运行
				try {
					Thread.sleep(100L);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				//获取任务锁
				lock.lock();
				try {
					//处理字典中数据
					for (;wordsIndex<words.length;wordsIndex++){
						//判断是否为元音
						if(isYuanWords(words[wordsIndex])){
							//打印元音字母
							System.out.println(" I am Ta Thread print YuanWord is *********** : "+ words[wordsIndex]);
						}else {
							//结束本次,等待下次获取任务
							System.out.println("我是线程TA:释放锁" + wordsIndex);
							break;
						}
					}
				}catch (Exception e){
					e.printStackTrace();
				}finally {
					//释放任务锁,让其它线程处理数据
					lock.unlock();
				}
			}
		}
	}

	public static class ThreadTwo implements Runnable {

		@Override
		public void run() {
			wordsIndex = 0;
			while (true) {
				//阻塞100ms,避免其它线程还未运行
				try {
					Thread.sleep(100L);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				//获取任务锁
				lock.lock();
				try{
					//处理字典中数据
					for (; wordsIndex < words.length; wordsIndex++) {
						//判断是否为元音
						if (!isYuanWords(words[wordsIndex])) {
							//打印非元音字母
							System.out.println(" I am Tb Thread print OtherWord is : " + words[wordsIndex]);
						} else {
							//结束本次,等待下次获取任务
							System.out.println("我是线程TB:释放锁" + wordsIndex);
							break;
						}
					}
				}catch (Exception e){
					e.printStackTrace();
				}finally {
					//释放任务锁,让其它线程处理数据
					lock.unlock();
				}
			}
		}
	}

	//判断是否为元音字母
	public static boolean isYuanWords(String word){
		//a, e, i, o, u
		if ("a".equals(word)) {
			return true;
		}else if ("e".equals(word)) {
			return true;
		}else if ("i".equals(word)) {
			return true;
		}else if ("o".equals(word)) {
			return true;
		}else if ("u".equals(word)) {
			return true;
		}else {
			return false;
		}
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值