1.java数据共享
线程创建方式
extend Thread ,启动时直接 对象调用start方法
public class MultiThread extends Thread{
@Override
public void run() {
while(true) {
System.out.println("111");
}
}
public static void main(String[] args) {
new MultiThread().start();
}
}
implements Runable接口 ,启动时要新建Thread,把实现接口对象带入 Thread中,然后启动。
public class MultiThread implements Runnable{
@Override
public void run() {
while(true) {
System.out.println("111");
}
}
public static void main(String[] args) {
MultiThread thread = new MultiThread();
//把runable对象带入Thread中启动
new Thread(thread,"thread1").start();;
}
}
java数据共享分析
例子引用自 https://blog.csdn.net/kong_gu_you_lan/article/details/57083185
对于例子中线程同步1的银行取钱问题,其调用过程如下,最终出现了 两个人短间隔各自取钱2000,取完后各自打印的余额结果却都是3000
public class ThreadTest {
public static void main(String[] args) {
// 创建一个账户,里面有存款5000元
Account account = new Account(5000);
// 模拟取钱过程
GetMoney getMoney = new GetMoney(account);
new Thread(getMoney, "你").start();
new Thread(getMoney, "你老婆").start();
}
}
因为两个线程传入了同一个对象getmoney,(Thread可见的代码并不是就是线程本身,Thread只是调用线程的API).对于这个例子,相当于传递给两个线程getmoney对象(内存地址的引用)进行处理,我获得getmoney时count值为5000,由于延时原因,此时妻子的线程也已经启动,此时妻子从内存获取的count值仍是5000,仍没有被修改,随后各自执行run方法,就各自显示了3000元余额。
共享数据解决方案synchronized
1.可以通过synchronized锁机制 synchronized(object)对资源上锁,保证同时只有object对象可以拥有共享资源。
synchronized可以修饰方法,代码块,和某一变量
public synchronizedvoid get(); 对方法上锁,等同于在方法内部添加代码块 public void get(){ sychronized(this){ //代码块} }
synchronized(this){ //代码块} 对一段代码上锁
synchronized(str1){ //处理逻辑 } 对变量str1上锁 ,上锁范围仅为{ }内的str1对象。
死锁的避免
当 两个进程 共享a,b变量,且要满足同时拥有才能完成操作,当出现各自拥有a,b,不释放a,b等待对方释放b,a的时候,就出现死锁。
public class MultiThread implements Runnable{
Integer a, b;
public MultiThread(int a, int b) {
this.a=a;
this.b=b;
}
@Override
public void run(){
try {
System.out.println("a+b的结果是 :"+count());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public int count() throws InterruptedException {
//必须把b写道a内部,才能保证同时拥有a,b才能完成操作。 不然存在资源被释放,不符合死锁条件。
synchronized(a){
System.out.println("a已被线程"+Thread.currentThread().getName()+"锁定");
Thread.sleep(100);
synchronized(b){
System.out.println("b已被线程"+Thread.currentThread().getName()+"锁定");
}
}
return a+b;
}
public static void main(String[] args) {
Integer a =40 , b = 60;
MultiThread thread1 = new MultiThread(a,b);
MultiThread thread2 = new MultiThread(b,a);
//把runnable对象带入Thread中启动
new Thread(thread1,"thread1").start();
new Thread(thread2,"thread2").start();;
}
}
执行结果
a已被线程thread1锁定
a已被线程thread2锁定
程序源码地址 :https://download.csdn.net/download/mychinasty/10925349
总结
1. 当出现资源共享,在设置锁的时候,要避免出现死锁
2. 本质讲,Thread是一个启动的载体,是线程操作的API, 其可控内容为 Thread创建的对象或者实现Runable接口的对象。启动多个Thread对同一个对象进行处理时,本质上多个线程都拥有该对象在内存中的内容。(对象的内存copy)。所以当多个Thread(对象,name);操作对象为同一个时,就会出现多个线程共享同一个对象的资源,资源共享。
3. sysnchronized(obj) 本质作用为obj对象在代码段,数据段,堆栈段的内容 (obj对象,可能是程序段,或者数据)
2.java线程状态
线程状态分类
新建状态:new Thread, 只是一个API的壳子,并未执行任何操作。
就绪状态:已获得除CPU之外的全部其他资源,在就绪队列中等待cpu。
阻塞状态:未获得运行所需资源而等待的状态,当获得完整之后,回插入就绪队列。
运行状态:线程正在执行的状态。当出现cpu时间片到期,会转变为就绪状态;运行期间缺少资源时,会转变为阻塞状态。
java中的线程状态
博客园的文章介绍的很好,链接如下 https://www.cnblogs.com/happy-coder/p/6587092.html
对于开发而言,线程的阻塞与唤醒 需要着重了解 ,归纳如下:
同步阻塞synchronized: 正在运行的线程未获得同步锁时,进入阻塞状态,不会释放自身已锁定的资源,当获得其余线程释放的同步锁以及其余资源时,转变为就绪状态。
wait()阻塞:线程主动阻塞,会释放自身的同步锁。需要主动唤醒才能解除wait()状态(notify()和notifyAll() Thread.interrupt()
等待时间过完),唤醒后一般仍未阻塞状态,需要等待重新获得同步锁及其他资源后,进入就绪状态。
sleep()阻塞:线程休眠,不放弃自身所持有的同步锁。超时后进入就绪状态。
join()阻塞:在执行线程中,调用其余线程的jion()方法。thread2.jion(),会等待thread2执行完后在执行当前线程,此时状态与sleep()类似。
yield()阻塞:线程从运行状态切换到阻塞状态,不释放本身同步锁。
interrupt()
待补充

697

被折叠的 条评论
为什么被折叠?



