更多干货,献给同样好奇的喵~~
- synchronized(this)锁定的是对象还是方法
- github上的开源的面试项目集锦
- 记录一次关于javamail连接邮件服务器发邮件报错Unable to find valid certification path to target request
初识线程,入个门
一、概念
- 进程和线程
(1)进程:查了百度百科的定义,太抽象,用任务管理器上的进程来理解吧。其实电脑上正在执行的任务程序就是我们说的‘进程’。
(2)线程:线程可以理解为进程中的独立运行的子任务。比如QQ.exe,在运行时,会有不同的子任务在并发运行,视频聊天,音乐,发图片,表情等等都有对应的线程在后台默默执行。
(3)多线程的好处:相比较单线任务,多任务执行可以提高程序运行效率,提高cpu使用率。
二、线程的使用
两种方式使用线程
(1)继承Thread类,覆盖父类的run方法.
class MyThread extends Thread {
@Override
public void run() {
System.out.println("MyThread");
}
}
(2) 实现Runable接口。
class MyThreadRunable implements Runnable {
@Override
public void run() {
System.out.println("MyThreadRunable");
}
}
Thread类也实现了Runable接口,意味着构造函数Thread(Runable target)可以接受实现了Runable接口的对象,还可传入Thread类的对象。
一个进程至少有一个线程在运行,java的main方法就是一个主线程,不过该线程是由jvm虚拟机创建的。
public class ThreadDemo {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName());
}
}
打印结果:
D:\DEV_Tools\JAVA\jdk1.8.0_25\bin\java "-javaagent:D:\DEV_Tools\IDE_Tools\IntelliJ IDEA\lib\idea_rt.jar=10283:D:\DEV_Tools\IDE_Tools\IntelliJ IDEA\bin" -Dfile.encoding=UTF-8 -classpath
main
Process finished with exit code 0
从打印结果可以看出,main就是主线程的名字。注意这里的main和main方法完全无关,只是名称相同而已。
代码运行结果和代码执行顺序的证明:
public class ThreadDemo {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
System.out.println("main");
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println("MyThread");
}
}
打印结果:
D:\DEV_Tools\JAVA\jdk1.8.0_25\bin\java "-javaagent:D:\DEV_Tools\IDE_Tools\IntelliJ IDEA\lib\idea_rt.jar=10522:D:\DEV_Tools\IDE_Tools\IntelliJ IDEA\bin"-
main
MyThread
Process finished with exit code 0
从结果看出,代码的运行和代码的执行顺序或调用顺序是无关的。原因是:线程是一个子任务,CPU以不确定的方式或者说是以一种随机的时间来调用线程中的run方法。注意如果多次调用start方法,会报异常IllegalThreadStateException。
下面这个例子充分说明线程的调用具有随机性:
public class ThreadDemo {
public static void main(String[] args) {
try {
MyThread myThread = new MyThread();
myThread.setName("myThread");
myThread.start();
for (int i = 0; i < 10; i++) {
int time = (int) (Math.random() * 1000);
Thread.sleep(time);
System.out.println("main = " + Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MyThread extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 10; i++) {
int time = (int) (Math.random() * 1000);
Thread.sleep(time);
System.out.println("run = " + Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
------------------------------------------------------------------------------
打印结果:
run = myThread
main = main
run = myThread
main = main
main = main
main = main
main = main
run = myThread
main = main
run = myThread
main = main
run = myThread
run = myThread
main = main
run = myThread
run = myThread
main = main
main = main
run = myThread
run = myThread
Process finished with exit code 0
另外还需要注意,start方法执行的顺序也不代表线程的启动顺序。如下例:
public class ThreadDemo {
public static void main(String[] args) {
MyThread myThread1 = new MyThread("线程1");
MyThread myThread2 = new MyThread("线程2");
MyThread myThread3 = new MyThread("线程3");
MyThread myThread4 = new MyThread("线程4");
MyThread myThread5 = new MyThread("线程5");
MyThread myThread6 = new MyThread("线程6");
MyThread myThread7 = new MyThread("线程7");
MyThread myThread8 = new MyThread("线程8");
myThread1.start();
myThread2.start();
myThread3.start();
myThread4.start();
myThread5.start();
myThread6.start();
myThread7.start();
myThread8.start();
}
}
class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println("当前线程为:" + Thread.currentThread().getName());
}
}
------------------------------------------------------------------------------
打印结果:
当前线程为:线程1
当前线程为:线程5
当前线程为:线程4
当前线程为:线程8
当前线程为:线程3
当前线程为:线程6
当前线程为:线程7
当前线程为:线程2
Process finished with exit code 0
如果想达到顶点,就从最底层开始吧。