以前在学Java的时候,没有仔细研究过多线程,后来在工作中也很少碰到,现在再捡起来学习一下。什么是多线程,经常和进程比较容易混淆,当程序启动以后,就会产生一个进程,而一个进程下面会有多个线程同步或者异步执行。
实现多线程的两种方式,在Java中可以通过实现Runable接口和继承Thread类来实现。
继承方式:
public class MyThread { public static void main(String[] args) { TestThread testThread=new TestThread("test thread"); testThread.start(); for (int i = 0; i < 100; i++) { System.out.println("main"+i); } } } class TestThread extends Thread{ public TestThread(String name){ super(name); } @Override public void run() { //每一个成员变量都有一个存储空间 int index=0; for (; index < 10; index++) { System.out.println(this.getName()+index); } } }1.继承thread
接口方式:
public static void main(String[] args) { ThredInterface interface1=new ThredInterface(); try { interface1.begin(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } class Mythread2 implements Runnable{ int index=0; private boolean flag=true; @Override public void run() { //需要多线程运行的程序 //共享成员变量,所有线程都来改 for (index=0; index < 2000; index++) { if(!flag)break; System.out.println(Thread.currentThread().getName()+index); } } public void stopThread(){ //释放资源 flag=false; } }1.实现runable接口
区别:
成员变量,继承的方式,是每个线程的成员变量都有一个存储空间,而接口的方式是所有线程共享一个成员变量,交替执行。
开发中一般使用接口方式调用,因为如果使用了继承的方式,那么该类就不能继承其他类了,而实现接口,可以实现多个接口。
常用方法:
为线程设置名称
thread中构造方法的第一个参数是实现runable接口的类,第二个参数就是线程名称
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
获取线程名称:Thread.currentThread().getName()
线程调度:
th.join();// 一直不轮换,当前线程必须走完
th.yield();// 暂时等待,不参与这一次的抢占-->到runable状态
但是线程的调度不能只通过这两个方法来控制
sleep休眠
stop停止线程,不建议使用 不安全,自己写一个停止的方法释放资源,定义一个stop线程的方法释放资源。
线程的状态:Runable runing blocked
线程同步:使用synchronized,可以在方法声明的时候标记,也可以使用一个key来作为线程同步块
synchronized (this) { Mythread2 m=new Mythread2(); Thread th=new Thread(m,"线程1"); //Thread th2=new Thread(m,"线程2"); th.start(); //th2.start(); while (true) { if (m.index==1000) { System.out.println("tingzhi"); th.stop(); //不安全 m.stopThread(); break; } } }
死锁:同步的嵌套的时候,线程之间相互等待
解决:同步的原子性放大,会降低效率,兼顾同步和效率
死锁程序:
public static void main(String[] args) { new TestLock().run(); } public void run(){ LockThread lockThread=new LockThread(); new Thread(lockThread,"线程一").start(); new Thread(lockThread,"线程二").start(); } class LockThread implements Runnable{ private Object k1=new Object(); private Object k2=new Object(); private boolean flag=true; @Override public void run() { if (flag) { flag=false; synchronized (k1) { System.out.println(Thread.currentThread().getName()+"k1"); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (k2) { System.out.println(Thread.currentThread().getName()+"k2"); } } }else{ flag=true; synchronized (k2) { System.out.println(Thread.currentThread().getName()+"k2..."); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (k1) { System.out.println(Thread.currentThread().getName()+"k1"); } } } } }