首页 > 编程语言 > 详细

线程总结

时间:2020-02-11 17:19:57      阅读:66      评论:0      收藏:0      [点我收藏+]

线程总结

线程主要涉及的内容以下几点

(以后有学习到新的再进行补充,新手描述嘤嘤嘤)


一.如何创建线程

??首先需要分清线程和进程之间的区别,简单的来说在java中执行一个可执行程序,可以称它为进程。在启动main方法时,就启动了一个java.exe进程。在main方法中还可以产生额外的线程(程序执行的最小单位),这样就包括了main线程和其他线程。
1、继承Thread

public class MyThread extends Thread  

{ 
//重写run方法
public void run()
{
//需要线程执行的代码
;
}
}
//start()为开始方法,只有执行了,线程才开始启动
new MyThread().start();

2、实现Runnable

public class MyThread implements Runnable
{ 
//重写run方法
public void run()
{
//需要线程执行的代码
;
}
}
new Thread(new MyThread()).start();

3、匿名类

new Thread()
{
public void run()
{
//需要线程执行的代码
;
}
}.start();

4、lambda表达式

//使用lambda表达式,只有在jdk8以后才可以用
new Thread(()->System.out.println("需要执行的代码")).start();

二、同步和互斥

??最开始我接触这个概念是在操作系统中,学到所谓的PV操作,进行互斥和同步的操作。在数据库中也涉及到并发下操作数据的影响,三类错误、读锁,写锁都是当初的内容。总而言之,就是互斥和同步是并发下正常执行必须要掌握的。(这里不介绍基本概念啦!)
1、线程的同步

线程会执行指定的run()方法,那么怎样让它一直执行呢?

new Thread()
{
public void run()
{
//加上这个语句就会一直执行了
while(true)
{
//需要线程执行的代码
;
}
}
}.start();

当多个线程一起执行的话就叫并发,这样如果一起对一个数据一起修改的话就出现错误。这时就需要使用关键字synchronized,使用synchronized会让被修饰对象无法被多个线程同时操作。

//方式一
synchronized(对象名){
//需要执行的代码
} 
//方式二 也可以放在方法前面
public synchronized void setName()
{
//对同一个实例对象,无法被多个线程同时执行
}

2、线程的互斥
如果想要一个线程在另一个线程之前执行,那么就需要互斥了。

//之前当前方法的线程会进行阻塞,并且释放对象锁(就是synchronized修饰的对象)
对象名.wait();
//如果需要唤醒就需要另外一个方法
对象名.notify()
对象名.notifyAll()

3、Thread的常用方法

//该线程休眠(暂停执行)1000毫秒=1s,如果有对象锁,也不会解开
Thread.sleep(1000);
//开始方法,不执行线程不会开始
Thread.start();
//使执行方法的对象线程加入到main线程中,执行完才继续mian线程
对象名.join()
//设置为守护线程
对象名.setDaemon(true);
//设置线程优先级
对象名.setPriority(Thread.MAX_PRIORITY);  

三、线程池

??如果使用太多的线程,大量的启动和结束动作会导致系统的性能变卡,响应变慢。所以使用线程池思想,会使线程重复使用,不必重复启动。(下面复制了qaq)

//jdk自带线程池
ThreadPoolExecutor threadPool= new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); 

第一个参数10 表示这个线程池初始化了10个线程在里面工作
第二个参数15 表示如果10个线程不够用了,就会自动增加到最多15个线程
第三个参数60 结合第四个参数TimeUnit.SECONDS,表示经过60秒,多出来的线程还没有接到活儿,就会回收,最后保持池子里就10个
第四个参数TimeUnit.SECONDS 如上
第五个参数 new LinkedBlockingQueue() 用来放任务的集合

然后使用
execute方法用于添加新的任务 

四、Lock锁

??Locksynchronized类似,都可以达到同步和互斥,但是Lock是程序实现,而后者语言自己实现。
1、使用

//Lock是个借口,需要找个类,这里使用 ReentrantLock 
Lock lock = new ReentrantLock();
//然后在需要位置,执行以下方法
lock.lock();
//需要解锁时使用,通常在finally中实现,文档推荐
lock.unlock()
//只要使用一个lock对象就可以解决指定对象的同步问题
Condition condition = lock.newCondition();
condition.await();//对应wait()
condition.signal();//对应notify()
condition.signalAll();//对应notifyAll();

2、区别
(copy qaq)

Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现,Lock是代码层面的实现。

Lock可以选择性的获取锁(trylock,解锁时需要判断是否有锁),如果一段时间获取不到,可以放弃。synchronized不行,会一根筋一直获取下去。 借助Lock的这个特性,就能够规避死锁,synchronized必须通过谨慎和良好的设计,才能减少死锁的发生。

synchronized在发生异常和同步块结束的时候,会自动释放锁。而Lock必须手动释放, 所以如果忘记了释放锁,一样会造成死锁。

3、对象锁
??对于一个萌新来说肯定疑惑过wait(),notify()这些方法一定要出现在对象锁之中吗?答案需要的,在百度之后发现,没有加synchronized也没有什么问题,但是这样是没有意义的,而且很可能会发生死锁。所以Lock就规定以一定要在lock()方法里面

五、原子操作

??原子操作就是不可拆分的操作,要么做,要么不做(就像是PV原语一样),如果分开操作,在并发下会造成数据的错误。

一、可用类

都在java.util.concurrent.atomic包,有用原子方法对int、int数组,boolean,long、long数组,对象引用,引用数组等进行操作方法

//jdk6以后
AtomicInteger atomicI =new AtomicInteger();
int i = atomicI.decrementAndGet();//减1
int j = atomicI.incrementAndGet();//加1
int k = atomicI.addAndGet(3);//与当前值相加,为负数是为减

本文为总结性文章,内容会有不足,请谅解。

参考内容 百度how2j

线程总结

原文:https://www.cnblogs.com/tddc10/p/12295481.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!