本章主要了解什么是进程?进程和线程有什么关系?有什么区别?以及创建线程的方式有哪些?
1.什么是进程?
简单的来说,进程是指在系统中正在运行的一个应用程序,每个进程之间是独立的,每个进程均运行在其专用的且受保护的内存。
2.什么是线程?
线程,又称轻量级进程(Light Weight Process)。
线程是进程中的一条执行路径,也是CPU的基本调度单位。
若一个程序可同一时间执行多个线程,就是支持多线程的.
一个进程由一个或多个线程组成,彼此间完成不同的工作(任务),
同时执行,称为多线程。
3.为什么使用多线程?
我们其实可以将这个问题换个角度思考,使用单线程处理问题时有什么不足?单线程处理方式在面对耗时任务时会导致程序阻塞,效率降低,并且CPU在等待I/O操作时资源利用率不高。相比之下,多线程通过并发执行多个任务,利用时间片轮转机制,提高了CPU资源的利用率,优化了I/O操作的等待时间,从而在宏观上实现了任务的并行处理。这种机制显著改善了用户体验,减少了等待时间,使得程序能够快速响应用户操作,同时进行多个任务,提高了整体的灵活性和效率。
4. java如何创建多线程
java中提供了三种实现多线程的方式:
第一种: 继承Thread类
第二种: 实现Runnable接口
第三种: 实现Callable接
4.1继承Thread类
第一种是使用继承Thread类来实现的
代码示例:接下来我们写一个小案例以便更好的理解,使用使用线程Thread类实现4个窗口各卖100张票
public class SellTicket extends Thread {
@Override
public void run() {
int tick = 100;
while (true) {
if (tick > 0) {
//getName获取线程名:默认的名称Thread-n. 该方法必须在Thread类下才能用
//Thread.currentThread():获取当前正在执行的线程对象
System.out.println(Thread.currentThread().getName() + "出售第" + tick + "张票");
tick--;
} else {
System.out.println("票卖完了");
break;
}
}
}
}
// 测试
public class SellTicketTest {
public static void main(String[] args) {
SellTicket sellTicket = new SellTicket();
//setName设置线程名
sellTicket.setName("线程A");
sellTicket.start();
SellTicket sellTicket1 = new SellTicket();
sellTicket1.setName("线程B");
sellTicket1.start();
}
}
4.2实现Runnable接口
第二种是实现Runnable接口来实现的
代码示例:接下来我们写一个小案例以便更好的理解,使用使用线程Thread类实现4个窗口共卖100张票
public class SellTicket implements Runnable {
private int tick = 100;
@Override
public void run() {
while (true) {
if (tick > 0) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
tick--;
System.out.println(Thread.currentThread().getName() + "卖了一张票;剩余:" + tick + "张");
} else {
break;
}
}
}
}
// 测试
public class TestTick {
public static void main(String[] args) {
SellTicket task=new SellTicket();
Thread t1=new Thread(task,"窗口A");
Thread t2=new Thread(task,"窗口B");
Thread t3=new Thread(task,"窗口C");
Thread t4=new Thread(task,"窗口D");
t1.start();
t2.start();
t3.start();
t4.start();
}
}
分析出: 超卖和重卖现象。 这是因为多个线程共享一个资源,导致了线程安全隐患问题。后期我们可以使用锁解决。
上两种方式继承Thread和实现Runnable那种方式比较好:
使用第二种,因为第二种的扩展性更好。
4.3实现Callable接口
Callable是一个接口(interface),它允许开发者定义一个可调用的任务,这个任务可以在多线程环境下执行,并且可以返回一个结果或者抛出一个异常。Callable接口的设计使得程序员可以使用多线程的方式来执行计算,并且能够获取到计算的结果或者处理任务执行过程中的异常情况。
代码示例: 创建线程计算1~1000之间求3倍数的和
public class MyCallable implements Callable<Integer> {
private int sum = 0;
@Override
public Integer call() throws Exception {
for (int i = 0; i < 1000; i++) {
if (i % 3 == 0){
sum += i;
}
}
return sum;
}
}
// 测试
public class Test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyCallable myCallable = new MyCallable();
FutureTask futureTask = new FutureTask(myCallable);
Thread t = new Thread(futureTask);
t.start();
Integer i = (Integer) futureTask.get();
System.out.println(i);
}
}
面试题总结:
1. 什么线程和进程?
2. 创建线程的方式?
3. Thread类中常用的方法。
4. Runable和Callable的区别?
1.Callable有返回值,而且抛出异常。而Runnable无返回值和异常抛出
2.Callable她是对Runnable的补充。