序
今天早上起床后,看见有朋友在群里发了个截图,关于一个Java程序员排序的截图,我看到了之后一时之间不是很清楚(好久没看过Java了,罪过罪过…),于是乎,我就翻了下以前的笔记,顺便整理下笔记。
线程排序法?
朋友发的图如下所示:
请原谅我第一时间并没有看懂里面的代码为啥可以排序啊,(哭泣-_-…),当然了后来一看就是利用sleep方法将线程沉睡就好了。
啥?你也不太相信这个能排序?好吧,代码拿去试试。
public class ArraySort implements Runnable{
private String num;
public ArraySort(int num) {
// TODO Auto-generated constructor stub
this.num=num+"";
}
public static void main(String[] args) {
int[] nums={11,3,998,5455,1,152,990};
for (int i = 0; i < nums.length; i++) {
new Thread(new ArraySort(nums[i])).start();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
try{
Thread.sleep(Integer.parseInt(num));
System.out.println(num);
}
catch(Exception e){
e.printStackTrace();
}
}
}
Java多线程机制
一个常识就是一台计算机是不可能拥有同时执行多个线程的能力的,哪怕是现在8核,还是12核,总是基于任务的快速切换。也就是说,计算机在任何时候都只能执行一个线程,为了建立这些线程同时执行的感觉,Java快速地控制从一个进程切换到另一个进程。
进程
程序的一次动态执行过程,它对应了从代码加载,执行至完毕的一个完整过程,也就是进程本省从产生,发展至消亡的过程。
线程
比进程更小的执行单位。
每一个Java程序都有一个默认的主线程,main()----->主线程
在这里只是简单讨论Thread和Runnable的线程使用方法,至于Callable方法先不谈,可以参考线程的三种创建方式
Thread类及其子类的对象来表示线程
一个新建的线程执行步骤:
- 新建
- 运行
start()方法
run ()方法----->具体的执行内容 - 中断
中断常用四种方法(可参考Java终止线程的四种方法) - 死亡
线程释放了实体,即释放分配给线程对象的内存
使用Thread类的 子类创建接口:
将类声明为 Thread 的子类。该子类应重写 Thread 类的 run 方法。接下来可以分配并启动该子类的实例。
- 继承Thread然后重写 run()方法
- 在main()中创建对象调用 run()方法
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
调用:
PrimeThread p = new PrimeThread(143);
p.start();
使用Runnable接口:
声明实现 Runnable 接口的类。该类然后实现 run 方法。然后可以分配该类的实例,在创建 Thread 时作为一个参数来传递并启动。
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
调用:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
总结:Thread(Runnable target)
- 创建线程对象时,向构造方法传递一个实现Runnable接口类的实例,该实例称为所创线程的目标对象。
- 对于Thread(Runnable target)构造方法创建的线程,当轮到它享用CPU资源时,目标对象就会自动调用接口中的 run()方法。
当然了,不同线程中的run()方法中的局部变量互不干扰
在线程中可以启动其他线程,(废话,不然main()咋调用其他线程)
关键点:接口调用
线程中常用方法:
- start()
- run()
- sleep(int millsecond)
在run()方法中调用sleep()方法使自己放弃CPU资源,休眠一段时间,如果在休眠时被打断,JVM会抛出interrupt异常,所以必须在try-catch中调用sleep()方法 - isAlive()
判断线程是否存活
注意:一个线程在还没有死亡前,不要再给其分配实体,由于线程只能引用最后的实体,先前的实体会成为垃圾,并且不会被垃圾回收机制回收掉。
- currentThread()
- interrupt()
吵醒休眠
线程的同步
关键词: ** synchronized**
当一个线程A使用synchronized修饰的方法时,其他线程想要使用这个方法就必须等待,直到线程使用完该方法。
所谓的线程同步就是若干个线程都需要使用一个synchronize方法
- wait()
中断方法的执行,使本线程等待,暂时让出CPU的使用权,并允许其他线程使用此同步方法 - notifyAll()
通知结束等待,先中断的先继续 - notify()
通知处于某一线程结束等待
线程的联合
A线程占用资源期间,可以让其他线程调用join()方法来和本线程联合。
例如:B.jion();
A线程执行期间---->B.join()---->执行B线程---->B结束
重新排队等待CPU资源,从中断处执行
如果A联合的B线程已经结束,那么B.join()无任何效果
守护线程
线程默认是非守护线程,非守护线程也叫用户线程。守护线程随时结束不会产生什么不良后果。
方法: setDaemon(boolean)