Java——线程与同步

2021/8/4 11:06:22

本文主要是介绍Java——线程与同步,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

线程与同步

多线程

在这里插入图片描述

  • 多个线程间互不影响
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——线程与同步的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程