1-1 进程
程序是静止的,运行中的程序就是进程。
- 进程的三个特征:
- 动态性 : 进程是运行中的程序,要动态的占用内存,CPU和网络等资源。
- 独立性 : 进程与进程之间是相关独立的,彼此有自己的独立内存区域。
- 并发性 : 假如CPU是单核,同一个时刻其实内存中只有一个进程在被执行。 CPU会分时轮询切换依次为每个进程服务,因为切换的速度非快,给我们的感觉这些进程在==同时执行,这就是并发性。==
- 并行:同一个时刻同时在执行。
1-2 线程
- 线程是属于进程的。==一个进程可以包含多个线程,这就是多线程==。线程创建开销相对于进程来说比较小。 线程也支持并发性。
- 线程的作用: 可以提高程序的效率,可以有更多机会得到CPU。
1-3 进程和线程的总结
进程是运行中的程序。有动态性,独立性,并发性。一个进程可以包含多个线程,线程也支持并发。
多线程可以提高程序的整体效率,可以解决很多业务需求。因为多个线程是并发抢占CPU执行,所以多线程的执行会出现随机性。
2-创建线程的三种方式
方式1:定义一个线程类继承Thread类,然后重写run()方法,再创建线程对象,调用start()方法启动线程
/**
方式一的步骤:a.定义一个线程类继承Thread类b.重写Thread类的run()方法c.创建一个子线程对象d.调用线程对象的start()方法启动线程(其实最终就是执行线程对象的run()方法)线程的注意:1.启动线程不能直接调用run()方法,否则是普通对象的普通方法调用了,将失去线程特征。线程的启动必须调用start()2.一般是先创建子线程,再申明主线程的任务,否则主线程任务总是先执行完!优缺点:优点:编码简单。缺点:线程类已经继承了Thread类,不能再继承其他类,功能被削弱了。不能做线程池。无法直接返回线程执行的结果。*/
public class ThreadDemo {// 自带一个线程:main方法本身就是一个线程,是最牛逼的线程!public static void main(String[] args) {// c.创建一个子线程对象MyThread t = new MyThread();// d.启动线程// 注意:启动线程不能直接调用run()方法,否则是普通对象的普通方法调用了,将失去线程特征。// 线程的启动必须调用start()t.start();for(int i = 0 ; i < 10; i++){System.out.println("main线程执行:"+i);}}
}// 线程类不是线程对象,是用来创建线程对象的。
// a.定义一个线程类继承Thread类
class MyThread extends Thread{// b.重写Thread类的run()方法@Overridepublic void run() {for(int i = 0 ; i < 10; i++){System.out.println("子线程执行:"+i);}}
}
方式2:定义一个线程任务类实现Runnable接口,然后重写run()方法。创建线程任务对象,把线程任务对象包装成线程对象,调用start()方法启动线程
/**
a.定义一个线程任务类实现Runnable接口。重写run()方法
b.创建一个线程任务对象
c.把线程任务对象包装成一个线程对象-- public Thread(Runnable target)
d.调用线程对象的start()方法启动线程。优缺点:缺点:编程相对复杂,不能直接返回线程的执行结果优点:1. 一个任务对象可以被反复包装成多个线程对象。2. 可以避免java中的单继承的局限性。因为线程任务对象只是实现了接口,还可以继续继承其他类和实现其他接口。3. 实现解耦操作,线程任务对象代码可以被多个线程共享,代码和线程独立。4. 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。适合做线程池。*/
public class ThreadDemo {public static void main(String[] args) {// b.创建一个线程任务对象Runnable target = new MyRunnable();// c.把线程任务对象包装成线程对象Thread t = new Thread(target);// d.调用线程对象的start()方法启动线程。t.start();Thread t1 = new Thread(target);t1.start();for(int i = 0 ; i < 10; i++){System.out.println(Thread.currentThread().getName()+"=>"+i);}}}
// 线程任务类
// a.定义一个线程任务类实现Runnable接口。
class MyRunnable implements Runnable{@Overridepublic void run() {for(int i = 0 ; i < 10; i++){System.out.println(Thread.currentThread().getName()+"=>"+i);}}
}
方式三:定义一个线程任务类实现Callable接口
/**
a.定义一个线程任务类实现Callable接口。
b.重写call()方法。
c.把线程任务对象包装成一个未来任务对象。
d.把未来任务对象包装成一个线程对象。
e.调用线程对象的start()方法启动线程。
优缺点:缺点:编码复杂。优点:全是优点。可以继续继承其他类。可以做线程池。可以得到线程返回的结果。可以做资源共享操作*/
public class ThreadDemo {public static void main(String[] args) {MyCallable call = new MyCallable();// c.把线程任务对象包装成一个未来任务对象。/*** 未来任务对象: FutureTask* 1.可以通过未来任务对象去获取线程执行的结果。* 2.未来任务对象其实就是一个Runnable的对象。*/FutureTask<String> target = new FutureTask<>(call);// d.把未来任务对象包装成一个线程对象。Thread t = new Thread(target);// e.调用线程对象的start()方法启动线程。t.start();for(int i = 0 ; i < 10; i++){System.out.println(Thread.currentThread().getName()+"=>"+i);}try {// 线程的执行的结果!String result = target.get();System.out.println(result);} catch (Exception e) {e.printStackTrace();}}
}
// a.定义一个线程任务类实现Callable接口。申明返回值类型
class MyCallable implements Callable<String>{// b.重写call()方法。@Overridepublic String call() throws Exception {int count = 0 ;for(int i = 0 ; i < 10; i++){count+=(i+1) ; // 1-10的和。System.out.println(Thread.currentThread().getName()+"=>"+i);}return Thread.currentThread().getName()+"求和结果:"+count;}
}