一:线程和进程的概念
1,进程:进程是操作系统的基础,是一次程序的执行;是一个程序及其数据在处理机上顺序执行时所发生的活动,是程序在一个数据集合上运行的过程,它是系统进行资源分配和调度的一个独立单位,一个进程至少一个线程。(比如windows系统中的进程列表)。
2,线程:线程可以理解为在进程中独立运行的子任务(比如QQ运行时候很多子任务在同时运行,视频线程,下载文件线程,发送表情线程等等)。
一个进程运行时至少一个线程在运行,Java中 public static void main()方法的线程就是由JVM创建的。
public class threadTest {
public static void main(String[] args) {
System.out.println("mian当前线程的名字:"+Thread.currentThread().getName());
}
}
运行结果:mian当前线程的名字:main
二:使用多线程的好处
可以最大限度的利用CPU的空闲时间来处理其他任务。(比如多任务操作系统一边打印机打印数据,一边使用word编辑文档,CPU在这些任务之间不停切换,似乎感觉同时运行),这是多线程技术的优点,使用多线程也就是在使用异步。
注意: 多线程是异步的,线程被调用是时机是随机的,编写的代码顺序并不是线程执行的顺序。
补充知识JAVA线程同步,异步,线程池
多线程并发时,多个线程同时请求同一个资源,必然导致此资源的数据不安全,A线程修改了B线程的处理的数据,而B线程又修改了A线程处理的数理。显然这是由于 全局资源造成的,有时为了解决此问题,优先考虑使用局部变量,退而求其次使用同步代码块,出于这样的安全考虑就必须牺牲系统处理性能,加在多线程并发时资源挣夺最激烈的地方,这就实现了线程的同步机制
同步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程请求不到,怎么办,A线程只能等待下去
异步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为没有同步机制存在,A线程仍然请求的到,A线程无需等待
三:实现多线程编程的方式主要有两种
1:继承Thread类(使用继承Thread类的缺点是不支持多继承,为了实现多继承可以实现Runnable接口的方式,一边实现一边继承)
public class MyThread extends Thread{
@Override
public void run() {
super.run();
System.out.println("执行MyThread线程:"+Thread.currentThread().getName());
}
}
public class threadTest {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.run();
System.out.println("运行mian线程的名字:"+Thread.currentThread().getName());
}
}
运行结果:
执行MyThread线程:main
运行mian线程的名字:main
或
运行mian线程的名字:main
执行MyThread线程:main
线程的随机性
例子一:
public class MyThread extends Thread{
@Override
public void run() {
try {
for(int i=0; i<8; i++){
int time = (int) (Math.random() * 1000);
Thread.sleep(time);//线程睡眠状态,暂停执行
System.out.println(i+",MyThread:"+Thread.currentThread().getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class threadTest {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.setName("myTh");//设置线程名称
myThread.start();//启动线程
try {
for(int i=0; i<8; i++){
int time = (int) (Math.random() * 1000);
Thread.sleep(time);//线程睡眠状态,暂停执行
System.out.println(i+",main:"+Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果:
0,MyThread:myTh
1,MyThread:myTh
0,mian:main
2,MyThread:myTh
1,mian:main
3,MyThread:myTh
4,MyThread:myTh
2,mian:main
5,MyThread:myTh
3,mian:main
6,MyThread:myTh
7,MyThread:myTh
4,mian:main
5,mian:main
6,mian:main
7,mian:main
例子二:
public class MyThread extends Thread {
private int i;
public MyThread(int i) {
super();
this.i = i;
}
@Override
public void run() {
System.out.println(i);
}
}
public class threadTest {
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();
}
}
运行结果:2 3 4 6 5 1 7 8
总结:使用多线程技术时,代码运行结果与代码执行顺序或调用顺序无关。线程是一个子任务,cpu以不确定的方式,或者说是已随机的时间来调用线程中的run方法。
线程启动顺序与start()执行顺序无关。
补充知识:
sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
在调用sleep()方法的过程中,线程不会释放对象锁。
2:实现Runnable接口
public class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("Runnable:"+Thread.currentThread().getName());
}
}
public class threadTest {
public static void main(String[] args) {
Runnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();
System.out.println("main:" + Thread.currentThread().getName());
}
}
运行结果
main:main
Runnable:Thread-0