进程是由线程组成的
线程本质是一个栈
一般是二十四十个线程比较合适(回答的时候答2040之间的具体一个数),一方面因为CPU有上下文切换,消耗时间;另一方面读写数据库单批次数据不能太大,太大会影响数据库的性能
下面代码,设置5个高优先级,5个低优先级,让10个线程处于就绪态,一起竞争资源,谁的count越大,谁竞争到的次数越多(优先级高的,竞争到的次数应该高)。
但是结果是,高优先级和低优先级count结果一样,说明设置的优先级没用
public class Priority {private static volatile boolean notStart = true;//为true,在29行的循环才能执行private static volatile boolean notEnd = true;//为true,在35行的循环才能执行public static void main(String[] args) throws Exception {List jobs = new ArrayList();for (int i = 0; i < 10; i++) {int priority = i < 5 Thread.MIN_PRIORITY : Thread.MAX_PRIORITY;Job job = new Job(priority);jobs.add(job);Thread thread = new Thread(job, "Thread:" + i);thread.setPriority(priority);thread.start();}notStart = false;//10个线程进入就绪态之后,notStart变为true,每个线程进入就绪态后都会进入第二个循环执行++操作TimeUnit.SECONDS.sleep(10);//10个线程竞争了10秒钟,在这之前会让jobCount++notEnd = false;for (Job job : jobs) {System.out.println("Job Priority : " + job.priority + ",Count : " + job.jobCount);}}static class Job implements Runnable {private int priority;//私有的,int类型的优先级private long jobCount;//工作次数public Job(int priority) {//指定这一次运行的优先级this.priority = priority;}public void run() {while (notStart) {//如果notStart为true,一直执行这个循环//先进入就绪态的线程,先执行的概率比较大hread.yield();//保证了公平//因为进入了运行状态但是没真正执行++操作,只是打空转后让出cpu//让出后重新进入就绪态,是操作系统记录位置,不是程序计数器}while (notEnd) {Thread.yield();//这句话是让出cpu的意思//为什么要加上这个(因为这个方法不靠谱,并不能立刻让出cpu,cpu会执行一段之间)//这个让出cpu后,会执行下面的++操作jobCount++;}}}
}

count数字这么大,也表示Thread.yield();方法不靠谱,并不是执行一次++操作就让出cpu,可能执行了1000次或10000次才让出cpu。
sleep(0)或sleep(1):可以立刻让出cpu
**线程状态:**新建状态,就绪状态,运行状态,阻塞状态,等待状态,终止状态(死亡状态)。


通过调用线程的start()方法进行启动,随着run()方法的执行完毕,线
程也随之终止
在运行线程之前首先要构造一个线程对象,线程对象在构造的时候需要提供线程所需要
的属性
==》如线程所属的线程组、线程优先级、是否是Daemon线程等信息(设置线程的父线程等)
==》可以通过构造方法加属性,也能通过其他方法加属性。
调用start()方法就可以启动这个线程。
中断好比其他线程对该线程打了个招呼,其他线程通过调用该线程的interrupt()
方法对其进行中断操作。
如何安全的终止线程
其他线程想让线程中断,需要在该线程中写代码配合, 如果只单纯的有其他线程调用该线程的中断方法,是不起任何作用的。
线程内需要配合,才能使这个线程中断

线程通过方法isInterrupted()来进行判断是否
被中断,也可以调用静态方法Thread.interrupted()对当前线程的中断标识位进行复位。
一个线程修改了一个对象的值,而另一个线程感知到了变化,然后进行相应的操作,整个
过程开始于一个线程,而最终执行又是另一个线程。
简单的办法是让消费者线程不断地循环检查变量是否符合预期。

上面这段伪代码在条件不满足时就睡眠一段时间,这样做的目的是防止过快的“无效”尝
试。
1)难以确保及时性。
2)难以降低开销。

示例:
WaitThread和NotifyThread,前者检查flag值是否为false,如果符合要求,进行后续操作,否则在lock上等待,后者在睡眠了一段时间后对lock进行通知。
(等待状态不会进入竞争,阻塞状态会被唤醒后参与竞争)

前面的章节介绍了等待/通知的经典范式,即加锁、条件循环和处理逻辑3个步骤,而这种
范式无法做到超时等待
假设超时时间段是T,那么可以推断出在当前时间now+T之后就会超时。
定义如下变量:

CountDownLatch属于线程同步的一种,让线程同时执行
CountDownLatch功能:
使用了CountDownLatch来确保ConnectionRunnerThread能够同时开始执行,并
且在全部结束之后,才使main线程从等待状态中返回。
