Java_多线程基础
-
什么是线程
-
为什么使用线程
-
java如何创建创建线程
-
线程中一些常见的方法
-
线程的状态有哪些
-
线程安全问题? 如何解决
-
线程通信
1. 什么是线程
(1) 什么是进程
正在运行的程序叫做进程, 进程是系统分配资源的基本单位. 使用 PID 来区分进程
(2) 什么是线程
进程中的一条执行路径,也是cpu的基本调度单位,一个进程由一个或多个线程组成,彼此之间完成不同工作,同时执行,称为多线程
(3) 进程和线程之间的区别 面试题
1. 进程是操作系统资源分配的基本单位,而线程是CPU的基本调度单位。
2. 一个程序运行后至少有一个进程。
3. 一个进程可以包含多个线程,但是至少需要有一个线程,否则这个进程是没有意义。
4. 进程间不能共享数据段地址,但是同进程的线程之间可以。
2. 为什么使用线程
为了解决负载均衡问题,充分利用CPU资源.为了提高CPU的使用率,采用多线程的方式去同时完成几件事情而不互相干扰.为了处理大量的IO操作时或处理的情况需要花费大量的时间等等,比如:读写文件,视频图像的采集,处理,显示,保存等
单核时代: 在单核时代多线程主要是为了提高 CPU 和 IO 设备的综合利用率。举个例子:当只有一个线程的时候会导致 CPU 计算时,IO 设备空闲;进行 IO 操作时,CPU 空闲。我们可以简单地说这两者的利用率目前都是 50%左右。但是当有两个线程的时候就不一样了,当一个线程执行 CPU 计算时,另外一个线程可以进行 IO 操作,这样两个的利用率就可以在理想情况下达到 100%了。多核时代: 多核时代多线程主要是为了提高 CPU 利用率。举个例子:假如我们要计算一个复杂的任务,我们只用一个线程的话,CPU 只会一个 CPU 核心被利用到,而创建多个线程就可以让多个 CPU 核心被利用到,这样就提高了 CPU 的利用率。
3. java如何创建创建线程?
通过继承Thread类
package com.qy143.demo01;
// 继承Thread类
public class MyThread extends Thread {
// 整个构造函数
public MyThread(String name) {
super(name);
}
// 重写run方法
测试
package com.qy143.demo01;
public class Test01 {
public static void main(String[] args) {
MyThread my1 = new MyThread("C");// 创建一个线程对象
//my1.setName("A");// 为线程起名
my1.start(); // 开启线程 当前线程和main线程同时正对实现
MyThread my2= new MyThread("D");// 创建一个线程对象
//my2.setName("B"); // 为线程起名
my2.start(); // 开启线程 当前线程和main线程同时正对实现
for (int i=0;i<10;i++){
System.out.println("main线程"+i);
}
}
}
为线程起名以及获取线程
1.获取线程名称
[1]this.getName();必须为Thread子类
[2]Thread.currentThread.getName();可在任意位置获取线程名称
2.为线程起名
[1]通过setName方法 该类对象必须为Thread的对象
[2]通过构造方法
实现Runnable接口
package com.qy143.demo03;
public class MyRunbable implements Runnable{
package com.qy143.demo03;
public class TestRunnable {
public static void main(String[] args) {
MyRunbable m1 = new MyRunbable(); // 线程任务
Thread t1 = new Thread(m1,"MyRunnable线程");
t1.start();
// 再整一个线程
Thread t2 = new Thread(m1,"MyRunnable线程2");
t2.start();
for (int i=0;i<10;i++){
System.out.println("main线程"+i);
}
}
}
例子: 四个窗口共卖100张票
package com.qy143.demo04;
public class TicketRunnable implements Runnable{
private int ticket=10;
public void run(){
while (ticket>0){
System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余:"+--ticket);
}
}
}
package com.qy143.demo04;
import com.qy143.demo02.TickThread;
import com.qy143.demo03.MyRunbable;
public class TestTicket {
public static void main(String[] args) {
TicketRunnable m = new TicketRunnable();
Thread t1 = new Thread(m,"窗口A");
Thread t2 = new Thread(m,"窗口B");
Thread t3 = new Thread(m,"窗口C");
Thread t4 = new Thread(m,"窗口D");
// 出现了重复?? 还有少的??
// 这就涉及到线程安全了
t1.start();
t2.start();
t3.start();
t4.start();
}
}
测试的结果 : 同一张票被多个窗口购买,而且出现负票,因为线程安全问题
4. 线程中一些常见的方法
休眠 : public static void sleep(long);
放弃 :public static void yield(); 放弃本次时间片,参与下次时间片的争夺
加入 :public void join();运行其他线程加入当前线程,直到其他线程运行结束后,当前线程才可以运行
优先级 :setPriority(); 值1-10 值越大获取cpu概率越大 默认可能为5
守护线程 : setDaemon(true); 所有前台线程结束后守护线程也会结束
5. 线程的状态(等待)
-
NEW---->start--->join--->Waiting
sleep----Time-waiting
Runnable
wating
限期等待 Timed Waiting 到期之后变为就绪状态
无限期等待 Waiting 条件满足之后才能变为就绪状态
blocked
TERMINATED
6 .线程安全问题? 如何解决
1.如何保证线程安全
(1) 使用同步代码块
使用一个对象类型作为锁
(2) 使用同步方法
默认使用this或者当前类作为锁
2.线程安全类有哪些
(1) Hashtable (2) StringBuffer (3) Vector (4) ConcurrentHashMap 这个贼叼 效率高还安全
Hashtable 和Hashmap的区别 :
-
线程安全
-
key和value是否允许null
-
效率上
-
HashMap的底层实现原理:
数组链表红黑树 ????
7. 线程通信
wait方法和sleep方法得区别?
(1)wait属于Object类,sleep属于Thread类 (2) wait会是否锁资源,sleep不会释放锁资源 (3) wait需要notify和notifyAll唤醒,sleep时间到了会自动唤醒。 (4) wait必须使用在同步代码块或者同步方法中, sleep可以在任何地方使用。
notify和notityAll得区别?
(1) notify随机唤醒等待队列中的某个线程, (2) notifyAll唤醒等待队列中所有的线程。
创建线程池得方式 :
package com.qy143.demo13;
import java.util.concurrent.*;
// Executor : 线程池顶级接口 execute方法
// ExecutorService : 顶级线程池子接口 shutdown 关闭线程池子 submit();该方法可以执行Runable类型和Callable类型的任务
// Executor : 工具类,相应的线程池
public class Test {
public static void main(String[] args) {
// 1. 固定长度的线程
ExecutorService executorService = Executors.newFixedThreadPool(3);
// 2. 长度可变线程 如果存在空闲的线程 则不会创建新的
//ExecutorService executorService = Executors.newCachedThreadPool();
// 3. 创建单一线程池 给队列使用
//ExecutorService executorService = Executors.newSingleThreadExecutor();
// 4. 创建定长延时线程池
//ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
// 5. ExecutorsService实现类创建.ThreadPoolExecutor
// ArrayBlockingQueue blockingQueue =new ArrayBlockingQueue(2);
// ExecutorService executorService =new ThreadPoolExecutor(3,5,5,TimeUnit.SECONDS,blockingQueue);
Runnable tast1 = new Runnable() {
扩充 :
Lock接口:
常用方法 : void lock(); // 获取锁 如锁被占用 则等待
boolean tryLock; // 尝试获取锁
void unnlock(); // 释放锁
实现类 :
重入锁 ReentrantLock
读写锁 ReentrantReadWriteLock
来个重点
啥是CAS
sysn和ReentLock的区别
????? 弄不明白去球吧

浙公网安备 33010602011771号