Java基础之多线程
一、线程基本知识
1、线程与进程
进程:执行中的程序
线程:轻量级的进程
线程本身不能单独进行,必须放在一个进程中才能执行。
2、Java的线程模型
1、新建状态
线程被创建之后便处于新建状态。
2、就绪状态
新建状态的线程调用start方法、进入就绪状态。
阻塞状态的线程解除阻塞之后进入就绪状态。
3、运行状态
处于就绪状态的线程获得cpu资源,该线程就进入了运行状态。
4、阻塞状态
是一个正在运行的线程因为一些原因让出cpu资源暂时中止而进入的状态。
5、终止状态
1、正常终止
2、强制终止:stop、destory System.exit(0)
3、异常终止:当线程执行过程中产生了异常,线程会终止。
二、继承Thread类创建线程
public class MyThread extends Thread{ public MyThread(String name) { super(name); } public void run() { for(int i=0;i<100;i++) { try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("MyThread"+i); } } }
public class ThradDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyThread mt=new MyThread("线程1");
mt.start();
MyThread mt2=new MyThread("线程2");
mt2.start();
for(int i=0;i<100;i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("主线程"+i);
}
System.out.println("程序执行完毕");
}
}
三、实现Runnable接口
1、实现Runnable接口
class A implements Runnable{ public void run(){ } }
A a=new A();
Thread t=new Thread(A);
Thread t1=new Thread(A,"线程1");
public class MyThread implements Runnable{ @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<10;i++) { try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("MyThread"+i); } } }
public class RunnableDemo { public static void main(String[] args) { // TODO Auto-generated method stub MyThread m=new MyThread(); Thread t=new Thread(m); t.start(); for(int i=0;i<10;i++) { try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("主线程"+i); } } }
2、两种方法比较
extends Thread
implements Runnable
单继承,多实现。
四、多线程应用
1、多个线程并发执行
Java对于线程启动后唯一能保证的是每个线程都被启动且结束。
但是对于哪个先执行,哪个后执行,什么时候执行是没有保证的。
2、线程优先级
Java中优先级高的线程有更大的可能性获得CPU,但不是优先级高的总是先执行,也不是优先级低的线程总不执行。
最高的优先级10,最低的优先级1
可以用setPriority()、getPriority()设置、获取优先级
public class MyRunnable implements Runnable{ @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<100;i++) { System.out.println("*"); } } }
public class MyRunnable1 implements Runnable{ @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<100;i++) { System.out.println("+"); } } }
public class Test { public static void main(String[] args) { // TODO Auto-generated method stub MyRunnable r=new MyRunnable(); MyRunnable1 r1=new MyRunnable1(); Thread t1=new Thread(r); Thread t2=new Thread(r1); System.out.println("t1的优先级"+t1.getPriority()); System.out.println("t2的优先级"+t2.getPriority()); t1.setPriority(Thread.MAX_PRIORITY); System.out.println("t1的优先级"+t1.getPriority()); t2.setPriority(Thread.MIN_PRIORITY); System.out.println("t2的优先级"+t2.getPriority()); t1.start();//就绪状态 t2.start();//就绪状态 } }
五、线程调度的三个方法
1、休眠方法sleep()
sleep(毫秒)、sleep(毫秒、纳秒)
public class TestSleep { public static void main(String[] args) { // TODO Auto-generated method stub for(int i=0;i<10;i++) { System.out.println(i); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
2、暂停方法yield()
a.yield()。a释放资源,大家抢资源。(a也会参与竞争)
public class TestYield { public static void main(String[] args) { // TODO Auto-generated method stub Thread t1=new Thread(new MyRunnable1()); Thread t2=new Thread(new MyRunnable2()); t1.start(); t2.start(); } } class MyRunnable1 implements Runnable{ @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<200;i++) { System.out.println("+"); Thread.yield(); } } } class MyRunnable2 implements Runnable{ @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<200;i++) { System.out.println("*"); Thread.yield(); } } }
3、挂起方法join()
a.join() 优先执行,相当于插队
public class TestJoin { public static void main(String[] args) { // TODO Auto-generated method stub MyThread m=new MyThread(); m.start(); for(int i=0;i<10;i++) { if(i==5) { try { m.join(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("++++++++++"); } } } class MyThread extends Thread{ public void run() { for(int i=0;i<10;i++) { System.out.println("**********"); } } }
六、同步问题Java解决方案
同步方法:当线程进入同步方法的时候,会获得同步方法所属对象的锁,一旦获得对象锁,则其他线程不能再执行被锁对象的其他任何同步方法。只有再同步方法执行完毕后释放了锁,其他线程才能执行。
synchronized 方法声明{}
同步块:
synchronized(资源对象){//需要进行同步的方法}
七、死锁问题
A线程需要申请资源1才能继续执行,而资源1被线程B所占用。而线程B需要申请资源2才能继续执行,而资源二被A线程所占有。
线程A占有资源2,需要申请资源1.
线程B占有资源1,需要申请资源2.
public class ResourceName { String resourceName; public ResourceName(String resourceName) { this.resourceName=resourceName; } }
public class MyThread extends Thread{ ResourceName r1; ResourceName r2; MyThread(ResourceName r1,ResourceName r2,String name){ super(name); this.r1=r1; this.r2=r2; } public void run() { synchronized(r1) { System.out.println(this.getName()+"获得了"+r1.resourceName); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(this.getName()+"在等待"+r2.resourceName); synchronized(r2) { System.out.println(this.getName()+"获得了"+r2.resourceName); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub ResourceName rs1=new ResourceName("资源1"); ResourceName rs2=new ResourceName("资源2"); ResourceName rs3=new ResourceName("资源3"); MyThread t1=new MyThread(rs1,rs2,"线程1"); MyThread t2=new MyThread(rs2,rs3,"线程2"); MyThread t3=new MyThread(rs3,rs1,"线程3"); t1.start(); t2.start(); t3.start(); } }