Java线程

线程

  1. 进程和线程

    进程和线程的概念:

    • 进程:就是一个运行的程序,默认有一个主线程
    • 线程:是进程中的一个任务,在一个进程中可以同时执行多个任务,称为多线程

    进程和线程的区别:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Aew9mkvX-1629291715338)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20210818094255264.png)]

    线程的组成

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QdXW0FeC-1629291715340)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20210818094746071.png)]

    ​ 线程的逻辑代码

  2. Java的线程实现方式

    1. 继承Thread类

      package com.qf.pro2103.day18;
      
      public class TestThread {
      
      	public static void main(String[] args) {
      		// TODO Auto-generated method stub
              Thread1 t1=new Thread1();
              Thread2 t2=new Thread2();
              t1.start();//可以让CPU执行任务,但不是马上执行
              t2.start();
              for(int k=1;k<=10;k++) {
              	System.out.println("k="+k);
              }
      	}
      
      }
      
      
      package com.qf.pro2103.day18;
      
      public class Thread1 extends Thread {
           public void run() {
          	 for(int i=1;i<=10;i++) {
          		 System.out.println("i="+i);
          	 }
           }
      }
      
    2. 实现进程接口(Runnable)

      package com.qf.pro2103.day18;
      
      public class Thread3 implements Runnable {
      
      	@Override
      	public void run() {
      		// TODO Auto-generated method stub
      		 for(int i=1;i<=10;i++) {
      			 try {
      				Thread.sleep(1000);
      			} catch (InterruptedException e) {
      				// TODO Auto-generated catch block
      				e.printStackTrace();
      			}
          		 System.out.println("i="+i);
          	 }
      	}
      
      }
      
      package com.qf.pro2103.day18;
      
      public class TestThread1 {
      
      	public static void main(String[] args) {
      		// TODO Auto-generated method stub
              Thread3 t3=new Thread3();
              Thread4 t4=new Thread4();
              Thread t31=new Thread(t3);
              Thread t41=new Thread(t4);
              t31.start();
              t41.start();
      	}
      
      }
      

    推荐使用接口

  3. 线程的状态及状态转换

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PUnRA6QR-1629291715342)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20210818111230229.png)]

    程序运行状态的线程进入到阻塞状态的方式之一:sleep(毫秒)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I5SxDt1w-1629291715344)(C:\Users\ASUS\AppData\Roaming\Typora\typora-user-images\image-20210818111457716.png)]

  4. 后台线程,线程让步,线程优先级等

    sleep(毫秒): 正在执行状态的线程,执行了sleep方法后就阻塞进入休眠状态,待休眠时间结束后,此线程自动进入就绪状态。

    yield()线程放弃,正在执行的线程,如果执行了yield方法,此线程由执行状态转变为就绪状态,等待CPU再次轮转

    join()线程结合,插队 当前线程正在执行过程中,如果某个线程执行了join(),则优先执行该线程,待该线程执行后,继续执行被插队的线程

    setPriority(10); //级别的数值越大,被CPU先执行的几率越高

    t2.setDaemon(true); 设置为后台线程

  5. 线程安全问题:

​ 多个线程操作同一“资源”

package com.qf.pro2103.day18;

public class MyArrayList implements Runnable {
	public static int index=0; //记录数组存放数据的位置
	public static String[] ary=new String[5];
	@Override
	public void run() {
		// TODO Auto-generated method stub
		ary[index]="hello";
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		index++;
	}
	
}
package com.qf.pro2103.day18;

public class ThreadSafe {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyArrayList mal=new MyArrayList();
		Thread t1=new Thread(mal);
		Thread t2=new Thread(mal);
		t1.start();
		t2.start();
		//输出数组内容
		try {
			Thread.sleep(1000);//线程给数组复制后,再执行下面的遍历
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		String[] ary=MyArrayList.ary;
		System.out.println("index="+MyArrayList.index);
		for(int i=0; i<ary.length; i++){
			System.out.println(ary[i]);
		}
	}

}

解决线程安全问题:使用锁

用锁把相关代码锁在一起,即使CUP轮转到其它线程,但是由于有锁,其它线程只能等待(阻塞),当锁释放后,其它线程竞争锁(CPU时间片轮转到哪个线程),

同步锁有两种用法:

1、同步代码块

synchronized(锁对象){

​ //锁住的代码

}

package com.qf.pro2103.day18;

public class MyArrayList implements Runnable {
	public static int index=0; //记录数组存放数据的位置
	public static String[] ary=new String[5];
	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized (this) {
			ary[index]="hello";
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			index++;
		}
	}
	
}

2、同步方法

用法:在方法的返回值类型前加关键字synchronized,意味着方法中的所有代码都在锁的范围内。

6.死锁问题

两个线程,互相等待对象释放锁对象

package com.qf.pro2103.day18.deadlock;

public class FoodLock {
	//任意非空对象都可以作为锁对象
	//一个锁对象只能同时为一个线程作为锁对象使用
	public static Object milk=new Object();
	public static Object bread=new Object();
}
package com.qf.pro2103.day18.deadlock;

public class Teacher implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized (FoodLock.bread) {
			System.out.println("Teacher已经拿到了面包,等待拿到牛奶");
			synchronized (FoodLock.milk) {
				System.out.println("Teacher已经拿到了牛奶,可以吃早餐了!");
			}
		}
	}

}

package com.qf.pro2103.day18.deadlock;

public class Student implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		synchronized (FoodLock.milk) {
			System.out.println("Student已经拿到了牛奶,等待获取面包");
			synchronized (FoodLock.bread) {
				System.out.println("Student拿到了面包,可以吃早餐了!");
			}
		}
	}

}
package com.qf.pro2103.day18.deadlock;

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Student jia=new Student();
		Teacher liu=new Teacher();
		Thread t1=new Thread(jia);
		Thread t2=new Thread(liu);
		t1.start();
		try {
			t1.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		t2.start();
		try {
			t2.join();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

避免死锁:

1、确定线程的先后执行顺序 join()

总结:

1、进程和线程区别

2、线程实现方式

3、线程的状态及状态的改变

4、重点:什么是线程安全问题

5、同步锁:两种用法

d catch block
e.printStackTrace();
}
t2.start();
try {
t2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}


避免死锁:

1、确定线程的先后执行顺序  join()

总结:

1、进程和线程区别

2、线程实现方式

3、线程的状态及状态的改变

4、重点:什么是线程安全问题

5、同步锁:两种用法

6、死锁问题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值