1、线程和进程
进程:一个程序,进程往往包含多个线程,至少包含一个
java 默认两个线程:main,GC
线程
Java能够开启线程吗?NO
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
//本地方法,底层调C++
private native void start0();
2、并发和并行
并发:多个线程操作同一资源
CPU一核,模拟出来多条线程
并行:多个人一起行走
CPU多核,多个线程可以同时执行,线程池
public class test1 {
public static void main(String[] args) {
//IO密集型
System.out.println(Runtime.getRuntime().availableProcessors());
}
}
并发编程的本质:充分利用CPU的资源
3、线程状态
public enum State {
//新生
NEW,
//运行
RUNNABLE,
//阻塞
BLOCKED,
//等待
WAITING,
//时间等待
TIMED_WAITING,
//结束
TERMINATED;
}
4、wait和sleep区别
wait属于Object类,sleep在JUC中
sleep不释放锁,wait释放锁
wait不需要捕获异常,sleep需要捕获异常
wait需在同步代码块中,sleep随时睡
5、lock锁
synchronize锁
并发:多线程在同一个资源类,把资源丢入线程
lambda表达式(参数)->{代码}
synchronize和lock区别
synchronize是内置的关键字,lock是java类
synchronize无法判断锁的状态,lock能判断锁的状态
synchronize会自动获取锁,lock必须手动释放锁,如果不释放会发生死锁
synchronize 线程:获取锁,阻塞,没获取锁,等待,lock可以尝试获取锁tryLock
synchronize:可重入锁,不可以中断,非公平,lock,可重入锁,可以判断锁,非公平(可设置公平)
synchronize,适合锁少量同步代码 lock适合锁大量同步代码
6、消费者和生产者
package com.gykj;
public class ProandConsu {
public static void main(String[] args) throws Exception{
Data data = new Data();
new Thread(()->{
for(int i=0;i<5;i++){
try {
data.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for(int i=0;i<5;i++){
try {
data.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
},"B").start();
}
}
//等待 业务 通知
class Data{
private int number=0;
public synchronized void increment() throws Exception{
if(number != 0){
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
public synchronized void decrement() throws Exception{
if (number == 0){
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
}
但当我们有多个加一线程,多个减一线程时,会出现虚假唤醒的线程,原因是因为我们的number判断时,if只判断了一次,当等待的线程再次拿到资源时,不再判断number状态,直接进行下面操作,就出错了,解决方法就是将if改成while
package com.gykj;
public class ProandConsu {
public static void main(String[] args) throws Exception{
Data data = new Data();
new Thread(()->{
for(int i=0;i<5;i++){
try {
data.increment();
} catch (Exception e) {
e.printStackTrace();
}
}
},"A").start();
new Thread(()->{
for(int i=0;i<5;i++){
try {
data.decrement();
} catch (Exception e) {
e.printStackTrace();
}
}
},"B").start();
}
}
//等待 业务 通知
class Data{
private int number=0;
public synchronized void increment() throws Exception{
while(number != 0){
this.wait();
}
number++;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
public synchronized void decrement() throws Exception{
while (number == 0){
this.wait();
}
number--;
System.out.println(Thread.currentThread().getName()+"=>"+number);
this.notifyAll();
}
}