文章目录提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
- 前言
- 1.什么是进程线程协程?
- 2.单核CPU设定多线程是否有意义?
- 3.线程数是不是越大越好
- 4.线程数设置多少最合适?
- 5.创建线程的五种方法?
- 6.java线程的6种状态?
- 7.线程的interruption?
前言
提示:这里可以添加本文要记录的大概内容:
个人的学习,仅供参考!
提示:以下是本篇文章正文内容,下面案例可供参考
1.什么是进程线程协程?进程:是操作系统对资源进行分配的基本单位,比如一个QQ程序,当可执行文件load到内存中则可生成一个进程。启动并登录多个QQ即创建了多个进程。
线程:是操作系统调度执行的基本单位,多个线程共享一个进程中所有的资源
协程:用户管理的(而不是OS管理的)线程
线程任务可能在等待IO任务,或处于sleep等,此时CPU处于空闲,所以即使单核CPU多线程依然可以更好的利用压榨CPU性能。
CPU密集性:大部分都在做计算操作,
IO密集性:大部分时间等待输入输出,等到后可能只执行一些简单的数据拷贝
线程的切换也是需要消耗资源的,如果线程数过大也可能会使CPU过于频繁的切换线程,浪费CPU性能。
可写代码验证。
公式:Nthreads=NCPU * UCPU *(1+W/C);
NCPU:是处理器的核的数目,可以通过Runtime.getRunTime().availableProcessors()得到
UCPU:是期望的CPU利用率(该值介于0-1之间)
W/C:是等待时间与计算时间的比率
W/C可以通过做实验日志、 JProfiler(生产环境)Arthas(上线或部署后)等工具进行测试统计得出。
可通过实际情景进行压测,找到最合适的数量。
1.继承Tread类重写run方法,new出对象后调用start方法。
2.实现runnable接口重写run方法,创建对象后将其当做参数创建Thread类的对象,调用start方法。(实现接口的方式更为灵活,还可进行继承其他类的操作)
3.使用lambda表达式,原理同上。
4.使用ThreadPool:
ExecutorService service = Executors.newCachedTreadPool();
service.execute(()->{
System.out.println("hello ThreadPool);
});
5.带返回值的任务执行:实现callable接口重写call方法。具体使用如下:
public class day03 {
static class MyCall implements Callable{
@Override
public String call() throws Exception {
System.out.println("Hello MyCall");
return "success";
}
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService service = Executors.newCachedThreadPool();
Future f = service.submit(new MyCall());
service.shutdown();
String s = f.get();
System.out.println(s);
}
}
运用FutureTask:
FutureTasktask = new FutureTask<>(new MyCall()); Thread t = new Thread(task); t.start(); System.out.println(task.get());
其实无论哪一种,最本质都是new了一个Thread类来启动线程。
6.java线程的6种状态?1.NEW:线程刚刚创建,还没有启动。
2.RUNNABLE:可运行状态,由线程调度器可以执行安排。
3.WAITING:等待被唤醒。
4.TIMED WAITING:间隔一段时间后自动唤醒。
5.BLOCKED:被阻塞,正在等待锁。
6.TERMINATED:线程结束。
如下图:
由下面代码测试可得知,只有synchronized锁住的线程才是BLOCKED,其他的也视为WAITING状态。
public class day03 {
static class SleepHelper {
public static void sleepSeconds(int seconds) {
seconds *= 1000;
try {
Thread.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
//===================================================================
Thread t1 = new Thread(() -> {
System.out.println("2: " + Thread.currentThread().getState());
for (int i = 0; i < 3; i++) {
SleepHelper.sleepSeconds(1);
System.out.print(i + " ");
}
System.out.println();
});
System.out.println("1: " + t1.getState());
t1.start();
t1.join();
System.out.println("3: " + t1.getState());
//===================================================================
Thread t2 = new Thread(() -> {
try {
LockSupport.park();
System.out.println("t2 go on!");
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t2.start();
TimeUnit.SECONDS.sleep(1);
System.out.println("4: " + t2.getState());
LockSupport.unpark(t2);
TimeUnit.SECONDS.sleep(1);
System.out.println("5: " + t2.getState());
//===================================================================
final Object o = new Object();
Thread t3 = new Thread(() -> {
synchronized (o) {
System.out.println("t3得到了锁 o");
}
});
new Thread(() -> {
synchronized (o) {
SleepHelper.sleepSeconds(5);
}
}).start();
SleepHelper.sleepSeconds(1);
t3.start();
SleepHelper.sleepSeconds(1);
System.out.println("6: " + t3.getState());
//===================================================================
final Lock lock = new ReentrantLock();
Thread t4 = new Thread(() -> {
lock.lock();
System.out.println("t4得到了锁 lock");
lock.unlock();
});
new Thread(() -> {
lock.lock();
SleepHelper.sleepSeconds(5);
lock.unlock();
}).start();
SleepHelper.sleepSeconds(1);
t4.start();
SleepHelper.sleepSeconds(1);
System.out.println("7: " + t4.getState());
//===================================================================
Thread t5 = new Thread(()->{
LockSupport.park();
});
t5.start();
SleepHelper.sleepSeconds(1);
System.out.println("8: "+t5.getState());
LockSupport.unpark(t5);
}
}
7.线程的interruption?
线程打断3方法:
interrupt() :打断某个线程(设置标志位)
isInterrupted():查询某线程是否被打断过(查询标志位)
static interrupted() :查询当前线程是否被打断过,并重置打断标志
使用方法如下:
public class day03 {
static class SleepHelper {
public static void sleepSeconds(int seconds) {
seconds *= 1000;
try {
Thread.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
for (;;){
if (Thread.currentThread().isInterrupted()){
System.out.println("Thread is interrupted!");
System.out.println(Thread.currentThread().isInterrupted());
break;
}
SleepHelper.sleepSeconds(1);
System.out.println("running...");
}
});
t.start();
SleepHelper.sleepSeconds(2);
t.interrupt();
}
}
interrputed()的使用:
public class day03 {
static class SleepHelper {
public static void sleepSeconds(int seconds) {
seconds *= 1000;
try {
Thread.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
for (;;){
if (Thread.currentThread().isInterrupted()){
System.out.println("Thread is interrupted!");
System.out.println("1: "+Thread.interrupted());
System.out.println("2: "+Thread.interrupted());
break;
}
}
});
t.start();
SleepHelper.sleepSeconds(2);
t.interrupt();
//思考一下,如果在这里写
System.out.println("main: "+t.interrupted());
//输出的是哪个线程的中断状态
}
}
当线程处于sleep()或wait()时使用interrput()方法,将会报错,且取消interrput的标记位。执行以下程序可验证。
但当wait()时使用interrupt()并不会影响线程对synchronize锁的持有,和后续执行,只是取消了interrput的标记位,且正处于的wait()会失效。
public class day03 {
static class SleepHelper {
public static void sleepSeconds(int seconds) {
seconds *= 1000;
try {
Thread.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
for (;;){
if (Thread.currentThread().isInterrupted()){
System.out.println("Thread is interrupted!");
System.out.println(Thread.currentThread().isInterrupted());
break;
}
SleepHelper.sleepSeconds(3);
System.out.println("running...");
}
});
t.start();
SleepHelper.sleepSeconds(2);
t.interrupt();
}
}
public class day03 {
static class SleepHelper {
public static void sleepSeconds(int seconds) {
seconds *= 1000;
try {
Thread.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static Object o = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
synchronized (o){
try {
o.wait();
} catch (InterruptedException e) {
System.out.println("Thread is interrupted");
System.out.println(Thread.currentThread().isInterrupted());
}
for (;;){
if (Thread.currentThread().isInterrupted()){
break;
}
SleepHelper.sleepSeconds(2);
System.out.println("running");
}
}
});
t.start();
SleepHelper.sleepSeconds(5);
t.interrupt();
// new Thread(()->{
// synchronized (o){
// o.notifyAll();
// }
// }).start();
}
}
在持有synchronize锁或锁的情况下,当sleep()时,使用interrupt(),会进行报错,但并不会影响线程持有锁,以及后续部分的执行。interrupt时的那次sleep()方法也会直接退出,继续往下执行。以下代码可验证
public class day03 {
static class SleepHelper {
public static void sleepSeconds(int seconds) {
seconds *= 1000;
try {
Thread.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static Object o = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
synchronized (o){
SleepHelper.sleepSeconds(15);
for (;;){
SleepHelper.sleepSeconds(1);
System.out.println(1);
}
}
});
t1.start();
SleepHelper.sleepSeconds(2);
Thread t2 = new Thread(()->{
synchronized (o){
}
System.out.println("t2 end");
});
t2.start();
t1.interrupt();
}
}
public class day03 {
static class SleepHelper {
public static void sleepSeconds(int seconds) {
seconds *= 1000;
try {
Thread.sleep(seconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
lock.lock();
SleepHelper.sleepSeconds(10);
try{
}finally {
lock.unlock();
}
System.out.println("t1 end");
});
t1.start();
SleepHelper.sleepSeconds(1);
Thread t2 = new Thread(() -> {
lock.lock();
try {
} finally {
lock.unlock();
}
System.out.println("t2 end");
});
t2.start();
SleepHelper.sleepSeconds(1);
t1.interrupt();
}
}
lock.lockInterruptibly()当由于sleep()时,被interrupt()导致报错时,可选择将锁释放。或不将锁释放,继续往下执行
public class day03 {
public static ReentrantLock lock = new ReentrantLock();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
int k;
try {
lock.lockInterruptibly();
Thread.sleep(10000);
System.out.println("锁没有被抢走");
Thread.sleep(10000);
System.out.println("你看是吧");
} catch (Exception e) {
e.printStackTrace();
System.out.println("警告");
return;
} finally {
lock.unlock();
}
System.out.println("t1 end");
});
t1.start();
Thread.sleep(1);
Thread t2 = new Thread(() -> {
try {
lock.lock();
System.out.println("t2running...");
Thread.sleep(5000);
}catch (Exception e){
e.printStackTrace();
}finally {
lock.unlock();
}
System.out.println("t2 end");
});
t2.start();
Thread.sleep(1);
t1.interrupt();
}
}



