进程和线程
- 进程:指的是正在运行的一个应用程序,是系统分配资源的独立单位,每一个进程都有它自己的内存空间和系统资源
- 线程:在一个进程内又可以执行多个任务,每个任务都可以看做是一个线程。线程是CPU调度的最小单位,线程没有自己的内存空间和资源。
- 线程的执行是有随机性的,我们无法确定在某一时刻执行的是哪个线程。
- jvm的启动是多线程的,至少包括主线程和垃圾回收线程(防止内存溢出)两个线程
多线程的实现方式:
继承Thread类,重写run方法,run()方法里面包含的是需要被线程执行的代码。
1.创建线程类:
public class MyThread extends Thread {
@Override
public void run() {
for(int i=0;i<10;i++)
System.out.print(i+" ");
}
}
2.创建多个线程,启动线程
public class MyThreadDemo {
public static void main(String[] args) {
MyThread m=new MyThread();
MyThread m2= new MyThread();
m.start();
m2.start();
}
}
3.执行结果:
//第一次:
0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9
//第二次:
0 0 1 2 3 1 2 4 3 4 5 5 6 7 8 9 6 7 8 9
//第三次:
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9
注意:
- 在启动线程的时候并不是直接调用run方法,而是调用start方法来启动线程,直接调用run 方法表示普通方法的调用,并不能体现多线程的效果,调用start方法是先启动线程,然后由jvm调用线程的run方法。
- 构造方法里面也可以传入参数,设置线程名,但是需要在子类中写构造方法。默认的线程名是:Thread-编号
public class MyThread extends Thread {
public MyThread() {
}
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for(int i=0;i<10;i++)
System.out.print(i+" ");
}
}
public class MyThreadDemo {
public static void main(String[] args) {
//默认线程名
MyThread m=new MyThread();
MyThread m2= new MyThread();
//m.start();
//m2.start();
//带参构造方法设置线程名
MyThread m3=new MyThread("线程3");
//seetName方法设置线程名
MyThread m4=new MyThread();
m4.setName("线程4");
System.out.println(m.getName());
System.out.println(m2.getName());
System.out.println(m3.getName());
System.out.println(m4.getName());
}
}
执行结果:
Thread-0
Thread-1
线程3
线程4
- 也可以使用
Thread.currentThread().getName()
方法获取线程名
public static Thread currentThread()是静态方法,返回当前正在执行的线程对象的引用
实现Runnable接口,实现run方法
public class MyRunnable implements Runnable {
//创建MyRunnable实现Runnable接口,实现run方法
@Override
public void run() {
for(int i=0;i<10;i++)
System.out.print(i+" ");
}
}
public class MyRunnableDemo {
public static void main(String[] args) {
MyRunnable my=new MyRunnable();//创建MyRunnable对象
//创建两个线程并将my对象作为参数
Thread t1=new Thread(my);
Thread t2=new Thread(my);
//启动两个线程
t1.start();
t2.start();
}
}
运行结果:
//第一次
0 0 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
//第二次
0 0 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
//第三次
0 1 2 3 4 0 1 2 3 4 5 6 7 8 9 5 6 7 8 9
//第四次
0 0 1 2 3 4 1 2 3 4 5 6 7 8 9 5 6 7 8 9
为什么有了方式一还要提供方式二:
- 因为方式一是继承Thread类,若一个类已经继承了某个类,此时它就不能继承Thread类了,方式二可以避免单继承的局限性。通常以方式二为主。
(个人学习总结,仅供参考)