林怼怼~~
就突然想到,程序员的粉丝都是程序员,当一个程序员看另一个程序员的代码时...嗯,你懂得
升级版怼怼
前言
--本篇内容整理线程相关知识复习巩固,属于三刷,
--解决windows下无法安装linux命令给git打差异包的问题
1.创建线程的方法?
有且仅有一个本质上就是new Thread(),至于runnable,callable,还是线程池ThreadPoolExecutor都是对调用run方法的一个扩展。
2.如何创建一个进程
public static void main(String[] args) throws InterruptedException, IOException {
Runtime runtime = Runtime.getRuntime();
Process exec = runtime.exec("cmd /k http://www.baidu.com");
exec.exitValue();
}
3.如何销毁一个线程?
java无法销毁一个线程,只能改变线程状态
当线程异常时,可视为中断销毁
但当thread.Alive返回false时已经被销毁
4.如何通过java API启动线程?
thread.start()
5.如何实现线程顺序打印?
方法1 join start
private static void threadJoinOneByOne() throws InterruptedException {
Thread t1 = new Thread(ThreadExecutionQuestion::action, "t1");
Thread t2 = new Thread(ThreadExecutionQuestion::action, "t2");
Thread t3 = new Thread(ThreadExecutionQuestion::action, "t3");
// start() 仅是通知线程启动
t1.start();
// join() 控制线程必须执行完成
t1.join();
t2.start();
t2.join();
t3.start();
t3.join();
}
方法2 isAlive自旋
private static void threadLoop() {
Thread t1 = new Thread(ThreadExecutionQuestion::action, "t1");
Thread t2 = new Thread(ThreadExecutionQuestion::action, "t2");
Thread t3 = new Thread(ThreadExecutionQuestion::action, "t3");
t1.start();
while (t1.isAlive()) {
// 自旋 Spin
}
t2.start();
while (t2.isAlive()) {
}
t3.start();
while (t3.isAlive()) {
}
}
方法3 方法2+sleep
private static void threadSleep() throws InterruptedException {
Thread t1 = new Thread(ThreadExecutionQuestion::action, "t1");
Thread t2 = new Thread(ThreadExecutionQuestion::action, "t2");
Thread t3 = new Thread(ThreadExecutionQuestion::action, "t3");
t1.start();
while (t1.isAlive()) {
// sleep
Thread.sleep(0);
}
t2.start();
while (t2.isAlive()) {
Thread.sleep(0);
}
t3.start();
while (t3.isAlive()) {
Thread.sleep(0);
}
}
方法4 join的实现
先判断线程状态没然后调用wait方法通知thread
private static void threadStartAndWait(Thread thread) {
if (Thread.State.NEW.equals(thread.getState())) {
thread.start();
}
while (thread.isAlive()) {
synchronized (thread) {
try {
thread.wait();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
其他实现countdownLatch,cyclicbarrier都是可以的
6.如何停止一个线程
开关法,
public class HowToStopThreadQuestion {
public static void main(String[] args) throws InterruptedException {
Action action = new Action();
// 子线程
Thread t1 = new Thread(action, "t1");
t1.start();
// 改变 action stopped 状态
action.setStopped(true);
t1.join();
Thread t2 = new Thread(() -> {
if (!Thread.currentThread().isInterrupted()) {
action();
}
}, "t2");
t2.start();
// 中断操作(仅仅设置状态,而并非中止线程)
t2.interrupt();
t2.join();
}
private static class Action implements Runnable {
// 线程安全问题,确保可见性(Happens-Before)
private volatile boolean stopped = false;
@Override
public void run() {
if (!stopped) {
// 执行动作
action();
}
}
public void setStopped(boolean stopped) {
this.stopped = stopped;
}
}
private static void action() {
System.out.printf("线程[%s] 正在执行...\n", Thread.currentThread().getName()); // 2
}
}
7为什么java要放弃stop方法
防止死锁
8.说明Thread interrupt,isinterrupted,interrupted 的区别和含义
Thread.interrupt() 设置状态
isInterrupted() 判断 返回Boolean
interrupted 即判断又清除
9.线程异常会发生什么?
发生异常时,isAlive会返回false,线程中断或销毁
10.如何捕获线程异常?
Thread.setDefaultUncaughtExceptionHandler源码
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new RuntimePermission("setDefaultUncaughtExceptionHandler")
);
}
defaultUncaughtExceptionHandler = eh;
}
public class ThreadExceptionQuestion {
public static void main(String[] args) throws InterruptedException {
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
System.out.printf("线程[%s] 遇到了异常,详细信息:%s\n",
thread.getName(),
throwable.getMessage());
});
// main 线程 -> 子线程
Thread t1 = new Thread(() -> {
throw new RuntimeException("数据达到阈值");
}, "t1");
t1.start();
// main 线程会中止吗?
t1.join();
// Java Thread 是一个包装,它由 GC 做垃圾回收
// JVM Thread 可能是一个 OS Thread,JVM 管理,
// 当线程执行完毕(正常或者异常)
System.out.println(t1.isAlive());
}
}
Connected to the target VM, address: '127.0.0.1:49192', transport: 'socket'
线程[t1] 遇到了异常,详细信息:数据达到阈值
false
Disconnected from the target VM, address: '127.0.0.1:49192', transport: 'socket'
捕捉到线程异常,避免线程并发异常堆栈溢出
插播【git clone 报错】解决方法
penSSL SSL_read: Connection was reset, errno 10054
在git clone vuex 项目时报错
是服务器的SSL证书没有经过第三方机构的签署,所以报错。
解决办法:
git config --global http.sslVerify "false"
11.当遇到异常时,线程池如何捕捉?
afterExecute方法
public static void main(String[] args) throws InterruptedException {
// ExecutorService executorService = Executors.newFixedThreadPool(2);
ThreadPoolExecutor executorService = new ThreadPoolExecutor(
1,
1,
0,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>()
) {
/**
* 通过覆盖 {@link ThreadPoolExecutor#afterExecute(Runnable, Throwable)} 达到获取异常的信息
* @param r
* @param t
*/
@Override
protected void afterExecute(Runnable r, Throwable t) {
System.out.printf("线程[%s] 遇到了异常,详细信息:%s\n",
Thread.currentThread().getName(),
t.getMessage());
}
};
executorService.execute(() -> {
throw new RuntimeException("数据达到阈值");
});
// 等待一秒钟,确保提交的任务完成
executorService.awaitTermination(1, TimeUnit.SECONDS);
// 关闭线程池
executorService.shutdown();
}
git diff windows解决无法用命令打差异包的问题。
git diff hotfix/0417 55ebcf7f6 --name-only --diff-filter=ACMR | xargs zip cloud.zip
试过很多方法去解决这个打差异包的问题,为了找出发版之间的增量代码,Windows下安装过http://www.cygwin.com/但无济于事
git小乌龟~Tortoisegit
在项目根路径右键
Diff with previous version
然后比较并去掉配置文件等导出,导出后打包~
本文内容根据B站UP主mercyblitz,2019.4.07期视频以及历史资料整理,扫描二维码关注小马哥公众号,java劝退师,好东西需要分享,干货满满