理解: 将一个程序比作高速收费站,那么一个收费窗口就是一个线程, 多个窗口就是多线程。
注意要点:
public class MyThread extends Thread{ @Override public void run() {//重写run()方法 for (int i = 0; i < 5; i++) System.out.println(Thread.currentThread().getName() + ":" + i); } }
public class Test { public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread();//这里创建第二个线程 t1.start(); t2.start(); } }
运行结果:
class MyThread implements Runnable{ int i = 10; @Override public void run() {//重写run()方法 while(i > 0) { System.out.println(Thread.currentThread().getName() + ":" + i--); } } } public class Test { public static void main(String[] args) { MyThread m = new MyThread(); Thread t1 = new Thread(m); t1.start(); } }
new Thread(){ @Override public void run() { //语句 } }.start();
方法名 | 作用 |
---|---|
getName() | 返回当前线程的名称 |
setName() | 设置当前线程的名称 |
currentThread() | 返回当前线程 (static方法) |
yeild() | a线程中调用a.yeild后CPU重新选择一个线程执行 |
join() | a线程中调用b.join后,a阻塞,b执行到结束后a再执行 |
sleep(x) | 当前线程阻塞x毫秒 (static方法) |
isAlive() | 返回当前线程是否存活 |
标识符 | 值 |
---|---|
MAX_PRIORITY | 10 |
NORM_PRIORITY | 5 |
MIN_PRIORITY | 1 |
方法 | 作用 |
---|---|
getPriority() | 返回线程的优先级 |
setPriority(x) | 将优先级设置为x |
多个线程在操作共享数据时可能会引发线程安全问题, 解决方法:
synchronized (obj) {//obj为锁,可以为任何对象 //操作共享数据的代码块 }
原理:被相同锁锁住的多个代码块一个执行完另一个才能开始执行
Runnable的方法实现多线程一般锁为 this
继承Thread的方法实现多线程锁一般为 子类类名.class
public synchronized void method(){ }
public class MyThread implements Runnable{ int i = 30; //JDK5.0开始的同步锁接口Lock() static ReentrantLock lock = new ReentrantLock();//ReentrantLock为Lock接口实现类 @Override public void run() { while(true) { lock.lock(); if (i > 0)//手动锁定 System.out.println(i--); else break; lock.unlock();//手动解锁 } } } public class Test { public static void main(String[] args) { MyThread m = new MyThread(); new Thread(m).start(); new Thread(m).start(); } }
死锁问题
public static void main(String[] args) { Object a = new Object(); Object b = new Object(); new Thread(){//线程一 @Override public void run() { synchronized(a){ System.out.println("a-"); try { sleep(1000);//sleep增加死锁概率 }catch (Exception e){ e.printStackTrace(); } synchronized(b){ System.out.println("a-b"); } } } }.start(); new Thread(){//线程二 @Override public void run() { synchronized(b){ System.out.println("b-"); try { sleep(1000); }catch (Exception e){ e.printStackTrace(); } synchronized(a){ System.out.println("b-a"); } } } }.start(); }
线程1:a锁嵌套b锁,
线程2:b锁嵌套a锁
如果线程一执行到b锁的同时,线程二执行到a锁,此时线程一的b锁无法开始执行(线程二占用),同理线程二里面的a锁也无法执行。 造成两线程阻塞,这就是死锁问题
输出如下:
线程通信的有关方法 (Object类的成员方法)
方法 | 作用 |
---|---|
wait() | 阻塞当前线程并解锁线程里的锁 |
notify() | 恢复含有的当前锁的另一个阻塞的线程(根据线程优先级) |
notifyAll() | 恢复含有当前锁的所有阻塞的线程 |
所有方法只能在同步代码块中调用且调用者是锁
public class MyThread implements Callable { @Override public Object call() throws Exception { System.out.println("线程执行中...."); return Integer.valueOf("20"); } } public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { MyThread m = new MyThread(); FutureTask f = new FutureTask(m);//返回值存储类 Thread t = new Thread(f); t.start(); //获取返回值 Object i = f.get(); System.out.println("返回值:" + i); }
这种方式可以实现泛型编程
public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { //ExecutorService为线程池的接口 //Executors为工具类,可以新建线程池 ExecutorService s = Executors.newFixedThreadPool(10);//10个线程的线程池 Object o = s.submit(new Callable(){//submit方法适用于callable @Override public Object call() throws Exception { System.out.println("callable执行中"); return null; } }).get(); s.execute(new Runnable() {//execute适用于Runnable @Override public void run() { System.out.println("Runable执行中"); } }); s.shutdown();//终止线程池 }
设置线程池属性方便管理
public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { ThreadPoolExecutor tp =(ThreadPoolExecutor) Executors.newFixedThreadPool(10); tp.setCorePoolSize(20);//线程池属性设置 tp.setMaximumPoolSize(100); } }