java多线程小抄(记录)

来源:互联网 发布:好用的祛痘洗面奶知乎 编辑:程序博客网 时间:2024/05/18 07:32

多线程的概念

进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程。线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换开销小。线程和进程一样分为五个阶段:创建、就绪、运行、阻塞、终止。多进程是  指操作系统能同时运行多个任务(程序)。多线程是指在同一程序中有多个顺序流在执行。

在java中创建一个线程有两种方法:

1 :实现java.lang.Runnable接口 重写run方法 启动 new Thread(this).start()2 :  继承java.lang.Thread类,重写run()方法。注意点:run并不是启动线程,而是简单的方法调用 并不是一启动线程(调用start()方法)就执行这个线程,而是进入就绪状态,什么时候运行要看CUP虽然两种方法都可行,但是最好还是用第一种方法,因为使用接口灵活性好,java中时单继承、多实现。Runnable可以多个线程共享同一资源

线程中的常用方法

1  sleep(long mills) 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。2  join():指等待t线程终止。也可以理解为将t线程合并到当前线程来,等待t线程结束后再往下执行。相当于方法调用3  yield():暂停当前正在执行的线程对象,并执行其他线程。4  setPriority(): 更改线程的优先级。 MIN_PRIORITY = 1  NORM_PRIORITY = 5  MAX_PRIORITY = 105  interrupt():中断某个线程,这种结束方式比较粗暴,如果t线程打开了某个资源还没来得及关闭也就是run方法还没有执行完就强制结束线程,会导致资源无法关闭 要想结束进程最好的办法就是用sleep()函数的例子程序里那样,在线程类里面用以个boolean型变量来控制run()方法什么时候结束,run()方法一结束,该线程也就结束了。6 this.interrupted  测试当前线程是否已经中断了 如果连续两次调用该方法 则第二次将返回false interrupted()方法具有清除状态的功能7 volatile的主要作用是使变量在多个线程可见。强制从公共堆栈中取的变量值,而不是从线程私有数据栈中取得变量值。但volatile关键字最致命的缺点是不支持原子性

synchroized和volatile的区别

1,关键字volatile是线程同步的轻量级实现,所以volatile性能肯定比synchronized要好,并且volatile只能修饰于变量,而synchronized可以修饰方法以及代码块2;多线程访问volatile不会发生阻塞,而synchronized会出现阻塞3volatile能保证数据的可见性,但不能保证原子性;而synchronized可以保证原子性,也间接保证可见性,因为它会将私有内存和公共内存中的数据做同步4;关键字volatile解决的是变量在多个线程之间的可见性,而synchronized关键字解决的是多个线程之间访问资源的同步性

线程间的通信之等待通知机智机制(wait,notify)

wait()方法 使线程停止运行1 使当前执行代码进行等待,将当前线程置于预执行队列中,是object类的方法,在wait方法所在的代码出停止执行,只到接到通知或被中断为止2 在调用wait方法前线程必须获得该对象的对象级别锁,只能在同步块或者同步方法中使用3 执行wailt方法后当前线程会释放锁,在从wait返回前,线程与其他线程竞争重新获得锁4 wailt方法没有持有适当的锁会抛出异常
notify()方法 使停止的线程继续运行1 必须在同步方法或者同步块中调用,线程必须获得该对象的对象锁2 有持有适当的锁会抛出异常3 该方法用来通知那些等待该对象的对象锁的其他线程,如果有多个线程,则由线程规划器随机挑选出其中一个呈wait状态的线程 对其出通知 并使他等待获取该对象的对象锁4 执行notify方法后,当前线程不会马上释放该对象的对象锁,呈wait状态的线程也并不能马上获取该对象锁,要等到执行notify方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才释放锁,呈wait状态的线程才可以获取对象锁

线程出现阻塞的情况大体分为5种

1 线程调用sleep方法 主动放弃占用的处理器资源2 线程调用了阻塞式IO方法,在该方法返回前 该线程被阻塞3 线程试图获得一个同步监视器,但该同步监视器正被其他线程持有4 线程等待某个通知5程序调用了suspend方法将该线程挂起。此方法容易导致死锁 

守护线程

调用thread.setDaemon(true)方法当前线程会变为守护线程且后续创建的新线程也都是守护线程主线程退出 守护线程也会随着退出synchronized关键字加到static静态方法上是给Class类上锁 而加到非static静态方法是给对象加锁 ,calss锁可以对类的所有实例起作用非线程安全问题存在于实例变量中 如果是方法内部的私有变量 则不再非线程安全问题,所得结果就是线程安全的了

为何要使用同步?

java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用, 从而保证了该变量的唯一性和准确性

实现同步的方式有几种,区别是什么?

synchronized(隐式锁):在需要同步的对象中加入此控制,synchronized可以加在方法上,也可以加在特定代码块中,括号中表示需要锁的对象。lock(显示锁):需要显示指定起始位置和终止位置。一般使用ReentrantLock类做为锁,多个线程中必须要使用一个ReentrantLock类做为对 象才能保证锁的生效。且在加锁和解锁处需要通过lock()和unlock()显示指出。所以一般会在finally块中写unlock()以防死锁。synchronized是托管给JVM执行的,而lock是java写的控制锁的代码synchronized和lock机制区别(1synchronized原始采用的是CPU悲观锁机制,即线程获得的是独占锁。独占锁意味着其 他线程只能依靠阻塞来等待线程释放锁。(2)Lock用的是乐观锁方式。所谓乐观锁就是,每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。乐观锁实现的机制就 是CAS操作(Compare and Swap)。简述synchronized和java.util.concurrent.locks.Lock的异同 ?主要相同点:Lock能完成synchronized所实现的所有功能主要不同点:synchronized会自动释放锁,而Lock一定要求程序员手工释放,并且必须在finally从句中释放

内置锁重人的概念

当某个线程请求一个由其他线程持有的锁时,发出请求的线程就会阻塞,然而,由于内置锁时可重入的,因此如果某个线程试图获得一个已经由它自己持有的锁 那么这个请求就会成功。“重入”意味着获取锁的操作的粒度是“线程”而不是“调用”,重入的一种实现方法是,为每个锁关联一个获取计数值和一个所有者线程,当计数值为0时,这个锁就被认为是没有任何线程持有。当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取计数值为1,如果同一个线程再次获取这个锁,计数值将递增,而当线程退出同步代码块时,计数器会相应地递减,当计数值为0时,这个锁将被释放

Java中sleep()和wait()的区别

1. 这两个方法来自不同的类,sleep方法属于Thread,wait方法属于Object。2. 最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。3. wait, notify和notifyAll只能在同步控制方法(synchronized)或者同步控制块里面使用,而sleep可以在任何地方使用。4. sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。
原创粉丝点击