线程
在java中,通过实现Runnable接口,可以实现多线程的创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class Thread_Test{ public static void main(String[] args) { Runnable t1 = ()->{System.out.println(Thread.currentThread().getName());}; Runnable t2 = ()->{System.out.println(Thread.currentThread().getName());}; Thread s = new Thread(t1); Thread m = new Thread(t2); m.start(); s.start(); } }
|
竞态条件
当有多个线程需要共享对同一数据的存取,并且都调用了要对对象进行修改的方法,就会发生竞态条件。因为这些方法是非原子的 ,即 读-处理-存储 并非是同一个操作,这时就会导致读取的数据可能在多个线程间被处理,导致最终的结果不稳定。
锁
通过定义锁结构,将一系列操作变为原子化操作,即在这一些列操作被完全执行前,其他线程无法对这个共享资源进行操作。
未加锁,非原子操作导致数据异常:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| public class Thread_Test{ static int count = 0; public static void main(String[] args) {
Runnable t1 = new Runnable() { public void run() { try { int i = 0; while (i < 100){ count++; i++; System.out.println("thread_name: "+ Thread.currentThread().getName() +"count : " + count); Thread.sleep(10); } }catch (InterruptedException e) { e.printStackTrace(); } } }; Runnable t2 = new Runnable() { public void run() { try { int i= 0; while ( i < 100){ count++; i++; System.out.println("thread_name: "+ Thread.currentThread().getName() +"count : " + count); Thread.sleep(10); } }catch (InterruptedException e) { e.printStackTrace(); } } }; Thread s = new Thread(t1); Thread m = new Thread(t2); m.start(); s.start(); } }
|
对共享变量 count 加锁,程序正常运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Thread_Test{ static Lock lock = new ReentrantLock(); static int count = 0; public static void main(String[] args) {
Runnable t1 = new Runnable() { public void run() { try { int i = 0; while (i < 100){ lock.lock(); count++; lock.unlock(); i++; System.out.println("thread_name: "+ Thread.currentThread().getName() +"count : " + count); Thread.sleep(10);
} }catch (InterruptedException e) { e.printStackTrace(); } } }; Runnable t2 = new Runnable() { public void run() { try { int i= 0; while ( i < 100){ lock.lock(); count++; lock.unlock(); i++; System.out.println("thread_name: "+ Thread.currentThread().getName() +"count : " + count); Thread.sleep(10);
} }catch (InterruptedException e) { e.printStackTrace(); } } }; Thread s = new Thread(t1); Thread m = new Thread(t2); m.start(); s.start(); } }
|
synchronized 关键字
synchronized 关键字本身是用来声明一个对象作为整体是只可以被某个线程所“独占”的。
所以通过以下几种方法可以定义不同的控制块
类型 |
加锁对象 |
影响范围 |
synchronized 实例方法 |
当前实例 (this ) |
同一个对象的同步方法互斥 |
synchronized 静态方法 |
当前类的 Class 对象 |
所有实例共享一把锁,互斥 |
synchronized (obj) |
自定义锁对象 (obj ) |
只在使用这把锁的代码块互斥 |
通过synchronized 来声明一个方法是一个线程安全的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class Thread_Test{ static Lock lock = new ReentrantLock(); static int count = 0; public static void main(String[] args) { Runnable storer = new Runnable() { @Override public void run() { try { for(int i = 0; i < 100; i++){ operation(-5); Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); }
}; }; Runnable getter = new Runnable() { @Override public void run() { try { for(int i = 0; i < 100; i++){ operation(5); Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); } }
}; ; Thread t1 = new Thread(storer); Thread t2 = new Thread(getter); t1.start(); t2.start(); } synchronized static void operation(int money){ count = count + money; System.out.println("current thread : " + Thread.currentThread().getName() + " , current count : " + count); } }
|
Object 的通知-等待
通过创建一个对象来,进行数据块的控制,
每个对象在JVM中有一个 监视器锁(Monitor) ,这是实现synchronized关键字背后的基础。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| import java.util.ArrayList; import java.util.List;
public class Thread_Test { static final Object lock = new Object(); static List<Integer> array = new ArrayList<>(10);
public static void main(String[] args) { Runnable producer = new Runnable() { @Override public void run() { try { for (int i = 0; i < 100; i++) { synchronized (lock) { while (array.size() == 10) { lock.wait(); } array.add(1); array.add(1); System.out.println("Producer added, size: " + array.size()); lock.notifyAll(); } Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); } } };
Runnable consumer = new Runnable() { @Override public void run() { try { for (int i = 0; i < 100; i++) { synchronized (lock) { while (array.size() <= 0) { lock.wait(); } array.remove(0); System.out.println("Consumer removed, size: " + array.size()); lock.notifyAll(); } Thread.sleep(100); } } catch (Exception e) { e.printStackTrace(); } } };
Thread t1 = new Thread(producer); Thread t2 = new Thread(consumer); t1.start(); t2.start(); } }
|
所以 控制竞态条件的操作有两种
1.lock + condition
1 2 3 4 5 6 7 8 9 10 11 12 13
| Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); lock.lock(); try { while (不满足条件) { condition.await(); } condition.signalAll(); } finally { lock.unlock(); }
|
2.synchronized + 对象块控制的等待,通知
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public Thread_Test() { array = new ArrayList<>(10); }
synchronized void store()throws InterruptedException{ while(this.array.size() >= 10){ wait(); } array.add(1); System.out.println(array.size()); notifyAll(); } synchronized void remove()throws InterruptedException{ while (this.array.size() <= 0){ wait(); } array.remove(0); System.out.println(array.size()); notifyAll(); }
|
Callable
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| import java.util.concurrent.Callable; import java.util.concurrent.FutureTask;
public class callable_test{ public static void main(String[] args) { A a = new A(); Callable<Integer> callable = () -> { for(int i =0 ;i < 100 ; i++){ a.num++; } return a.num; }; var futuretask = new FutureTask<Integer>(callable); new Thread(futuretask).start(); try { Integer num = futuretask.get(); } catch (Exception e) { e.printStackTrace(); }finally{ System.out.println(a.num); }
} }
class A { int num = 1; }
|
使用执行器
向线程池提交线程
1 2 3 4 5 6 7 8
| Future<T> submit(Callable<T> task) Future<T> submit(Runable task) Future<T> submit(Runable task ,T task)
var futuretask = new FutureTask<Integer>(callable); ExecutorService executor = Executors.newCachedThreadPool(); executor.submit(futuretask); executor.shutdown();
|
异步
异步本身是为了解决线程执行过程中 线程阻塞导致整体执行效率降低的问题。
在所有流程被串行执行时,流程中的任务等待响应阻塞后续任务的执行。
ComplateFuture
进程
java中创建进程
通过ProcessBuilder来进行进程创建。
java中的进程创建是向操作系统申请创建一个全新的进程,并不与
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| var builder = new ProcessBuilder("gcc","myapp.c")
builder = builder.directory(path.toFile());
OutStream processln = p.getOutputStream(); InputStream processOut = p.getInputStream(); InputStream processError = p.getErrorStream();
Process process = new ProcessBuilder("/bin/s","-l"); .directory(Path.of("/tmp").toFile()) .start();
try (var in = new Scanner(process.getInputStream())){ while (in.hasNextLine()) System.out.println(in.nextLine()); }
int result = process.waitFor();
long delay = ... ; if (process.waitfor(delay,TimeUnit.SECONDS)){ int result = process.exitValue(); ... }else { process.destroyForcibly(); }
process.onExit().thenAccept( p->System.out.println("Exit value : "+ p.exitValue()));
|