java多线程
java线程实现方式
- 继承Thread类
- 实现Runnable方法
- Callable接口
1.继承Thread类
package thread; import java.util.Random; /** * 使用Thread的方式实现多线程 */ public class Match1 { public static void main(String[] args) { Runner liuxiang = new Runner();//创建一个新的錢程 liuxiang.setName("刘翔"); Runner lufei = new Runner();//创建一个新的錢程 lufei.setName("路飞"); Runner wuqin = new Runner();//创建一个新的錢程 wuqin.setName("吴钦"); wuqin.start();//启动线程 lufei.start();//启动线程 liuxiang.start();//启动线程 } } class Runner extends Thread { @Override public void run() { int speed = new Random().nextInt(100); for (int i = 1; i <= 100; i++) { //this.getName() 打印当前线程的名字 System.out.println(this.getName() + "已前进 " + (i * speed) + "米(" + speed + "米/s)"); } } }
以上代码中有5个线程:main主线程,继承Thread的三个线程,回收线程(垃圾回收线程)
2.实现Runnable方法
package thread; import java.util.Random; /** * 实现Runnable的方式实现多线程 */ public class Match2 { public static void main(String[] args) { Runner2 liuxiang = new Runner2();//创建一个新的线程 Thread thread = new Thread(liuxiang); thread.setName("刘翔"); thread.start(); Runner2 lufei = new Runner2();//创建一个新的线程 Thread thread1 = new Thread(lufei); thread1.setName("路飞"); thread1.start(); } } class Runner2 implements Runnable{ @Override public void run() { int speed = new Random().nextInt(100); for (int i = 1; i <= 100; i++) { //this.getName() 打印当前线程的名字 System.out.println(Thread.currentThread().getName() + "已前进 " + (i * speed) + "米(" + speed + "米/s)"); } } }
3.实现Callable
并发工具包-Concurrent:
JDK1.5提供了一个并发工具包java.util.concurrentjava.util.concurrent
包含许多线程安全、测试良好、高性能的并发构建块。创建 concurrent 的目的就是要实现 Collection 框架对数据结构所执行的并发操作。
通过提供一组可靠的、高性能并发构建块,开发人员可以提高并发类的线程安全、可伸缩性、性能、可读性和可靠性。
package thread; import java.util.Random; import java.util.concurrent.*; /** * 实现Callable的方式实现多线程 */ public class Match3 { public static void main(String[] args) throws ExecutionException, InterruptedException { //创建一个新的线程池 ExecutorService executorService = Executors.newFixedThreadPool(3); Runner3 liu = new Runner3(); liu.setName("liu"); Future<Integer> future = executorService.submit(liu); Runner3 wuqin = new Runner3(); wuqin.setName("wuqin"); Future<Integer> future1 = executorService.submit(wuqin); executorService.shutdown(); System.out.println("liu累计跑了" + future.get() + "米"); System.out.println("wuqin累计跑了" + future1.get() + "米"); } } class Runner3 implements Callable<Integer> { private String name; public void setName(String name) { this.name = name; } @Override public Integer call() throws Exception { int speed = new Random().nextInt(100); int distinct = 0; for (int i = 1; i <= 100; i++) { distinct = i * speed; //this.getName() 打印当前线程的名字 System.out.println(this.name + "已前进 " + (i * speed) + "米(" + speed + "米/s)"); } return distinct; } }
三种方式总结
线程同步机制
Synchronize的使用场景:
Synchronize可以使用在以下三种场景,对应不同锁对象:
- synchronized代码块 - 任意对象即可
- synchronized方法 - this当前对象
- synchronized静态方法 - 该类的字节码对
package thread; import java.util.Random; /** * Synchronize代码块 */ public class SyncSample { public static void main(String[] args) { Couplet couplet = new Couplet(); for (int i =0;i<100;i++){ new Thread(() -> { int r =new Random().nextInt(2); if(r==1){ couplet.first(); }else { couplet.second(); } }).start(); } } } class Couplet{ final Object lock = new Object(); public void first(){ synchronized (lock){ System.out.print("琴"); System.out.print("棋"); System.out.print("书"); System.out.print("画"); System.out.println(); } } public void second(){ synchronized (lock){ System.out.print("柴"); System.out.print("米"); System.out.print("油"); System.out.print("盐"); System.out.println(); } } }
package thread; import java.util.Random; /** * Synchronize方法 */ public class SyncSample { public static void main(String[] args) { Couplet couplet = new Couplet(); for (int i = 0; i < 100; i++) { new Thread(() -> { int r = new Random().nextInt(2); if (r == 1) { couplet.first(); } else { couplet.second(); } }).start(); } } } class Couplet { public synchronized void first() { System.out.print("琴"); System.out.print("棋"); System.out.print("书"); System.out.print("画"); System.out.println(); } public void second() { synchronized (this) { System.out.print("柴"); System.out.print("米"); System.out.print("油"); System.out.print("盐"); System.out.println(); } } }
package thread; import java.util.Random; /** * Synchronize静态方法 */ public class SyncSample { public static void main(String[] args) { for (int i = 0; i < 100; i++) { new Thread(() -> { int r = new Random().nextInt(2); if (r == 1) { Couplet.first(); } else { Couplet.second(); } }).start(); } } } class Couplet { public synchronized static void first() { System.out.print("琴"); System.out.print("棋"); System.out.print("书"); System.out.print("画"); System.out.println(); } public static void second() { synchronized (Couplet.class) { System.out.print("柴"); System.out.print("米"); System.out.print("油"); System.out.print("盐"); System.out.println(); } } }
线程的五种状态:
死锁
死锁的产生:
package thread; public class DeadLock { private static final String fileA = "A"; private static final String fileB = "B"; public static void main(String[] args) { new Thread(() -> { while (true) { synchronized (fileA) { System.out.println(Thread.currentThread().getName() + "文件A写入"); synchronized (fileB) { System.out.println(Thread.currentThread().getName() + "文件b写入"); } System.out.println(Thread.currentThread().getName() + "所有文件保存完成"); } } }).start(); new Thread(() -> { while (true) { synchronized (fileB) { System.out.println(Thread.currentThread().getName() + "文件B写入"); synchronized (fileA) { System.out.println(Thread.currentThread().getName() + "文件A写入"); } System.out.println(Thread.currentThread().getName() + "所有文件保存完成"); } } }).start(); } }
线程安全
在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。
线程安全/不安全的类:
- Vector是线程安全的,ArrayList、LinkedList是线程不安全的
- Properties是线程安全的,HashSet、TreeSet是不安全的
- StringBuffer是线程安全的,StringBuilder是线程不安全的
- HashTable是线程安全的,HashMap是线程不安全的