1线程

 

 

 

用户线程是主线程创建的线程 

GC线程是为守护线程,主要回收主线程;

线程分为守护线程和非守护线程(即用户线程)。
只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结 束时,守护线程随着 JVM 一同结束工作。 守护线程最典型的应用就是 GC (垃圾回收器)。

 

现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行

 

public class JoinThreadDemo02 {
	public static void main(String[] args) {
		Thread t1 = new Thread(new Runnable() {
			public void run() {
				for (int i = 0; i < 20; i++) {
					System.out.println("t1,i:" + i);
				}
			}
		});
		Thread t2 = new Thread(new Runnable() {
			public void run() {
				try {
					t1.join();
				} catch (Exception e) {
					// TODO: handle exception
				}
				for (int i = 0; i < 20; i++) {
					System.out.println("t2,i:" + i);
				}
			}
		});
		Thread t3 = new Thread(new Runnable() {
			public void run() {
				try {
					t2.join();
				} catch (Exception e) {
					// TODO: handle exception
				}
				for (int i = 0; i < 20; i++) {
					System.out.println("t3,i:" + i);
				}
			}
		});
		t1.start();
		t2.start();
		t3.start();
	}
}

多线程分批处理

线程安全

线程安全解决问题

 

同步保证数据的安全问题

同步函数:用的是this锁

静态同步函数

下面验证静态同步函数使用当前字节码文件作为锁

多线程死锁

多线程三大特性

  原子性  可见性  有序性

  Java内存模型分为主内存和私有本地内存,产生线程安全

共享内存模型指的就是Java内存模型(简称JMM),JMM决定一个线程对共享变量的写入时,能对另一个线程可见。从抽象的角度来看,JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。

总结:什么是Java内存模型:java内存模型简称jmm,定义了一个线程对另一个线程可见。共享变量存放在主内存中,每个线程都有自己的本地内存,当多个线程同时访问一个数据的时候,可能本地内存没有及时刷新到主内存,所以就会发生线程安全问题。

Volatile:与java内存模型有关

     作用:保证线程之间可见,不保证原子性 

已经将结果设置为fasle为什么?还一直在运行呢。

原因:线程之间是不可见的,读取的是副本,没有及时读取到主内存结果。

解决办法使用Volatile关键字将解决线程之间可见性, 强制线程每次读取该值的时候都去“主内存”中取值

AtomicInteger是一个提供原子操作的Integer类,通过线程安全的方式操作加减

jdk1.5并发包

程序同步:程序从上向下的有顺序执行

线程同步:保证线程安全,保证数据的原子性。

多线程之间实现通讯

wait()、notify()、notifyAll()是三个定义在Object类里的方法,可以用来控制线程的状态。

这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。

 如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。

如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。

如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。

注意:一定要在线程同步(synchronized)中使用,并且是同一个锁的资源  

wait()、notify()同时使用

 

wait和sleep区别

jdk1.5 lock锁 保证线程安全

Lock 接口与 synchronized 关键字的区别

Lock 接口可以尝试非阻塞地获取锁 当前线程尝试获取锁。如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁。
Lock 接口能被中断地获取锁 与 synchronized 不同,获取到锁的线程能够响应中断,当获取到的锁的线程被中断时,中断异常将会被抛出,同时锁会被释放。

Lock 接口在指定的截止时间之前获取锁,如果截止时间到了依旧无法获取锁,则返回。

class Res {

	public String userName;
	public String sex;
	// true 生产者线程等待,消費可以进行消费 false 生成者可以写, 消费者变为等待
	public boolean flag = false;
	Lock lock = new ReentrantLock();
	
}

class Out extends Thread {
	Res res;
	Condition newCondition;
	public Out(Res res,Condition newCondition) {
		this.res = res;
		this.newCondition=newCondition;
	}

	@Override
	public void run() {
		// 写的操作 0 1
		int count = 0;
		while (true) {
			try {
				res.lock.lock();
				if (res.flag) {
					try {
						newCondition.await();;// 让当前线程 从运行状态变为休眠状态 并且释放锁的资源
					} catch (Exception e) {
						// TODO: handle exception
					}

				}
			
				if (count == 0) {
					res.userName = "小红";
					res.sex = "女";
				} else {
					res.userName = "余胜军";
					res.sex = "男";
				}
				// 计算奇数或者偶数公式
				count = (count + 1) % 2;
				res.flag = true;
				// 唤醒
				newCondition.signal();
			} catch (Exception e) {
				// TODO: handle exception
			}finally{
				res.lock.unlock();
			}
			
		}

	}

}

class Input extends Thread {
	Res res;
	Condition newCondition;
	public Input(Res res,Condition newCondition) {
		this.res = res;
		this.newCondition=newCondition;
	}

	@Override
	public void run() {
		while (true) {
			try {
				// 上锁
				res.lock.lock();
				if (!res.flag) {
					try {
						newCondition.await();
					} catch (Exception e) {
						// TODO: handle exception
					}
				}
			
				System.out.println(res.userName + "," + res.sex);
				res.flag = false;
				newCondition.signal();
			} catch (Exception e) {
				// TODO: handle exception
			}finally{
				// 释放锁
				res.lock.unlock();
			}
		
		}

	}
}

public class OutInputThread {
	public static void main(String[] args) {
		Res res = new Res();
		Condition newCondition = res.lock.newCondition();
		Out out = new Out(res,newCondition);
	
		Input input = new Input(res,newCondition);
		out.start();
		input.start();
	}

}

 

停止线程思路

   1.  使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。

    2.  使用stop方法强行终止线程(这个方法不推荐使用,因为stopsuspendresume一样,也可能发生不可预料的结果)。

    3.  使用interrupt方法中断线程。

ThreadLocal提供一个线程的局部变量,访问某个线程拥有自己局部变量。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值