day18--线程

线程

一、内容回顾

1、java集合框架的组成

2、ArrayList和LinkedList的区别是什么

3、ArrayList是如何添加数据的

4、HashMap是如何存放数据的

5、如何给ArrayList中的对象按某个属性排序?

6、java处理异常的方式有哪些?

7、Throw和Throws的区别是什么?

8、遍历Map集合有哪些方式?

二、今日内容

1、进程和线程的区别

2、java的线程实现方式

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

4、后台线程、线程让步、线程优先级等

1、进程和线程的区别

进程:就是一个运行的程序,默认有一个主线程

线程:是进程中的一个任务,在一个进程中可以同时执行多个任务,称为多线程

2、java多线程实现方式

1、继承Thread类
package com.qf.pro2103.day18;

public class Thread1 extends Thread {

	public void run(){
		//任务
		for(int j=1; j<=10; j++){
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.println("j="+j);
		}
	}
}

package com.qf.pro2103.day18;

public class Demo2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		System.out.println(Thread.currentThread().getName());
		
		Thread1 t1=new Thread1();
		Thread2 t2=new Thread2();
		t1.start();//可以让CPU执行任务run(),但不是立刻执行
		t2.start();
		for(int k=1;k<=10;k++){
			System.out.println("k="+k);
		}
	}

}

2、实现Runnable接口
package com.qf.pro2103.day18;

public class Thread3 implements Runnable {

	@Override
	public void run() {
		// TODO Auto-generated method stub
		for(int k=1;k<=10;k++){
			System.out.println("k="+k);
		}
	}

}
package com.qf.pro2103.day18;

public class Demo3 {

	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、线程状态

出行运行状态的线程进入到阻塞状态的方式之一:sleep(毫秒),在休眠时间结束后,自动进入到就绪状态

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]);
		}
	}

}

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

用锁把相关代码锁在一起,即使CPU轮转到其它线程,但是由于有锁,其它线程只能等待(阻塞),当锁释放后,其它线程竞争锁(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、同步锁:两种用法

{
// 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、同步锁:两种用法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值