ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java——线程与同步

2021-08-04 11:02:15  阅读:99  来源: 互联网

标签:同步 Java Thread sum 线程 void println public


线程与同步

多线程

在这里插入图片描述

  • 多个线程间互不影响
public class myThread extends Thread{
	@Override
	public void run() {
		// TODO Auto-generated method stub
//		String name = getName();
//		//getname 返回线程名称
//		System.out.println(name);
		
		Thread t = Thread.currentThread();//获取当前正在执行的线程
		System.out.println(t);
		String name = t.getName();
		System.out.println(name);
	}
}

//测试程序
public class thread_demo {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		myThread myt = new myThread();
		myt.start();
		new myThread().start();//创建多线程
		
		System.out.println(Thread.currentThread().getName());
		//获取主线程名称
	}
}

sleep

  • 使当前正在执行的线程以指定的毫秒数暂时停止运行
  • 毫秒记时后再开始运行

创建多线程

  1. start
  2. runnable
//runable
public class runnabledd implements Runnable{
	//重写run方法
	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int i = 0;i<20;i++) {
			System.out.println(Thread.currentThread().getName()+"-->"+i);
		}
	}
}

//测试类
public static void main(String[] args) {
		// TODO Auto-generated method stub
		runnabledd run = new runnabledd();//接口的使用方法
		Thread mt = new Thread(run);
		for(int i = 0;i<20;i++) {
			System.out.println(Thread.currentThread().getName()+"-->"+i);
		}
		mt.start();
	}
	
//俩个线程争夺运行
  1. 匿名内部类实现创建线程
    • 简化代码
    • 使用线程的内匿名内部类方式,可以方便的实现每个线程执行不同的线程任务操作。 使用匿名内部类的方式实现Runnable接口,重新Runnable接口中的run方法:
public class 匿名内部类创建线程 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		new Thread() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				for(int i = 0;i<10;i++) {
					System.out.println(Thread.currentThread().getName()+"mt");
				}
			}
		}.start();
        
		Runnable run = new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				for(int i = 0;i<10;i++) {
					System.out.println(Thread.currentThread().getName()+"kik");
				}
			}
		};
		
		new Thread(run).start();//当然也可把runnable重写方法这些的过程直接放到括号内以简化
		
	}

}

实现runnable接口创建多线程程序的好处

  1. 避免了单继承的局限性(否则如果继承了Thread就不能继承其他类了)
  2. 增强程序的扩展性,降低程序的耦合性

线程安全

案例

public class runnabledd implements Runnable{
	private int sum = 50;
	@Override
	public void run() {
		//买票的安全问题
		while(true) {
			if(sum>0) {//这里如果设置了!=0,则会导致错误,因为多线卖票,可能导致没有等于0就走了
				System.out.println("卖出第"+sum+"号票");
				sum--;
			}
			else {
				break;
			}
		}
	}
}
//实现多个Thread使用new出的runnabledd,输出时有多次卖出相同号票

产生原因

多个线程共享数据时,每一条代码运行间都有时间间隔,可能刚好本次线程执行间隙,另一个线程开始执行,导致出现了案例中的问题

解决

使用同步代码块

public class runnabledd implements Runnable{
	private int sum = 50;
	Object ob = new Object();
	//这里创建了一个对象
	@Override
	public void run() {
		// TODO Auto-generated method stub		
		//买票的安全问题	
		while(true) {
			//创建锁对象
			synchronized (ob) {
				if(sum>0) {
					System.out.println(Thread.currentThread().getName()+"卖出第"+sum+"号票");
					sum--;
				}
				else {
					break;
				}
			}
		}
	}
}

同步中的线程,没有执行完毕不会释放锁;同步外的线程没有锁进不去同步。

使用同步方法

  1. 把访问了共享数据的代码抽取出来,放到一个方法中
  2. 在方法上添加synchronized
public synchronized void ticket() {
		while(true) {
			//创建锁对象
				if(sum>0) {
					System.out.println(Thread.currentThread().getName()+"卖出第"+sum+"号票");
					sum--;
				}
				else {
					break;
				}
			
		}
	}
//静态同步方法
/*方法前加static,注意的是使用的变量也应该是静态变量,静态方法的锁对象是本类的 class属性*/

使用lock锁

  1. 成员位置创建一个Reentrantlock对象
  2. 在可能出现安全问题的代码前调用lock接口中的lock方法
  3. 在。。。后用unlock方法
Lock lock = new ReentrantLock();//在run方法外写

while(true) {
			lock.lock();
			if(sum>0) {
				System.out.println(Thread.currentThread().getName()+"卖出第"+sum+"号票");
				sum--;
			}
			else {
				break;
			}
			lock.unlock();
		}

等待唤醒

package javaee.process;

public class 等待唤醒案例 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Object obj = new Object();
		new Thread() {
            public void run() {
                while(true) {
                    synchronized (obj) {
                        try {
                            System.out.println("买包子");
                            obj.wait();//进入等待状态
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }//唤醒	
                    }
                    System.out.println("吃包子");
                    System.out.println("------------------");
                }
			};
		}.start();
		new Thread() {
			public void run() {
				while(true) {
					try {
						Thread.sleep(2000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					synchronized (obj) {
						obj.notify();//唤醒线程	
					}					
					System.out.println("做好了");
				}
			};
		}.start();		
	}
}

wait()方法进入等待,等其他的进程的notify()唤醒。
wait()方法中也可以传参数(毫秒值),当记时结束则会自动唤醒,不需要其他的进程的notify()。
notifyall()方法唤醒监视器中所有等待的线程

标签:同步,Java,Thread,sum,线程,void,println,public
来源: https://www.cnblogs.com/waydmt/p/15097917.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有