线程状态、线程调度、线程安全、多线程、同步方法、同步代码块

发布于:2023-01-11 ⋅ 阅读:(441) ⋅ 点赞:(0)

线程状态:

        创建状态---》就绪状态----》运行状态-----》阻塞状态----》死亡状态

 

线程调度:线程调度指按照特定机制为多个线程分配Cpu的使用权

        方法:

                void setPriorrity (int newPriority)                 更改线程的优先级

MyRunnable mr = new MyRunnable();
		
		Thread t1 = new Thread(mr, "线程A");
		Thread t2 = new Thread(mr, "线程B");
		//输出两个线程的优先级
		System.out.println(t1.getPriority());
		System.out.println(t2.getPriority());
		//更改线程优先级
		t1.setPriority(t1.MAX_PRIORITY);
		t2.setPriority(t2.MIN_PRIORITY);
	
		System.out.println(t1.getPriority());
		System.out.println(t2.getPriority());
		//线程优先级高只能说明线程获取的cpu资源的该路大一些,不能保证每一次优先级高的线程先获取cpu资源

        static void sleep(long millis)                 在指定的毫秒数内让当前正在执行的线程休眠

//线程延迟
			Thread.sleep(5000);`//休眠5秒

        viod join()                 等待该线程终止

//线程强制执行:t1强制执行,一直等到t1执行完毕之后,才会释放Cpu资源给其他线程执行,在调用join()方法之前,多个线程依然是抢占cpu
					t1.join();
//millis:一毫秒为单位的等待时长
//nanos:要等待的附加纳秒时长
//需要处理InterruptedException异常

        static void yield()         暂停当前执行的线程对象,并执行其他线程

//线程礼让:让当前执行run()方法的线程释放Cpu资源,给其他线程一个获得CPU资源的一个机会,但是当前线程还会抢占Cpu资源,也就是说,当前线程释放CPU,就看其他线程能不能抓住这个机会
				Thread.yield();
//暂停当前线程,允许其他具有相同优先级的线程获得运行机会
//该线程处于就绪状态,不转为阻塞状态
//只是一种可能,但是不能保证一定会实现礼让

                void interrupt()         中断线程

               boolean isAive()         测试线程是否处于活动状态

多线程共享数据引发的问题

        多个线程操作同一共享数据资源时,将引发数据不安全问题

                在一个线程中操作共享数据的时候,还没有操作完毕,线程失去了CPU资源,CPU资源被另外一个线程获取,另外一个线程会接着上一个线程操作数据继续执行操作,

               当另一个线程操作数据完毕之后,第一个线程又获取了CPU资源,此时,第一个线程看到的数据时第二个线程操作后的数据,由此就会引发数据不安全问题

同步方法:

                使用synchronized修饰的方法控制对类成员的变量的访问

                访问修饰符 synchronized 返回类型方法名(参数列表){}或者synchronized 访问修饰符 返回类型 方法名(参数列表){}

//定义属性表示票库里的票数
	private int count = 10;
	//定义属性表示用户买到的是第几张票
	private int num = 0;

	@Override
	 public  void run() {
		while(true){
			if(!sale()){
				break;
			}
		}
		}
			public synchronized boolean sale(){
		// 如果票的数量小于,就不再买票
		if (count<=0) {
			return false;
		}
		//每卖出一张票,总数-1,卖出去的票数+1
		count--;
		num++;
		//模拟网络延迟
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//输出
		System.out.println(Thread.currentThread().getName()+"买到了"+num+"张票,还剩"+count+"票");
		return true;
	}

                将线程要操作的代码放入同步方法中,当线程执行到同步方法的时候,一定会执行完同步方法里所有代码后在释放cpu资源,从而一个线程对数据的操作不会受其他线程的影响

同步代码块

                使用synchronized关键字修饰的代码块:synchronized(syncObject){//需要同步的代码块}

                syncObject为同步的对象,通常this

public void run() {
		while(true){
			//同步代码块
			synchronized (this){
				// 如果票的数量小于,就不再买票
				if (count<=0) {
					break;
				}
				//每卖出一张票,总数-1,卖出去的票数+1
				count--;
				num++;
				//模拟网络延迟
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				//输出
				System.out.println(Thread.currentThread().getName()+"买到了"+num+"张票,还剩"+count+"票");
			}
		}
		}

多个并发线程访问同一资源的同步代码块时

                同一时刻只能有一个线程进入synchronized(this)同步代码块

                当一个线程访问一个synchroized(this)同步代码块时,其他synchroized(this同步代码块同样的被锁定

                当一个线程访问一个synchronized(this)同步代码块时,其他线程可以分为该资源的非synchronized(this)同步代码

线程安全的类型

                ArrayList类的add()方法为非同步方法,当多个线程向同一个ArrayList对象添加数据时,可能出现数据不一致问题

方法是否同步 效率 适用场景
线程安全 多线程并发共享资源
非线程安全 单线程

常见的类型比较

        Hashtable&&HashMap

        Hashtable:继承关系实现了Map接口,Hashtable继承Dictionary类,线程安全,效率较低键和值都不允许为null

        HashMap:继承关系实现了Map接口,继承AbstractMap类,非线程安全,效率较高键和值都允许为null

StringBuffer&&StringBuilder

        前者线程安全,后者非线程安全


网站公告

今日签到

点亮在社区的每一天
去签到