1、基本概念
程序:是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。
进程:则是执行程序的一次执行过程,它是一个动态的概念。是系统资源分配的单位。
通常一个进程中可以包含若干个线程。线程是CPU调度和执行的单位
很多多线程是模拟出来的,真正的多线程是指有多个CPU,即多核,如服务器。
如果是模拟出来的多线程,即在一个CPU的情况下,在同一个时间点,CPU只能执行一个代码,因为切换很快,所以会有同时执行的错觉。
线程就是独立的执行路径;
在程序运行时,即使没有自己创建线程,后台也会有多个线程,如主线程,gc线程;
main()称之为主线程,为系统的入口,用于执行整个程序;
在一个进程中,如果开辟了多个线程,线程的运行由调度器安排调度,调度器是与
操作系统紧密相关的,先后顺序是不能人为的干预的。
对同一份资源操作时, 会存在资源抢夺的问题,需要加入并发控制;
线程会带来额外的开销, 如cpu调度时间,并发控制开销。
每个线程在自己的工作内存交互,内存控制不当会造成数据不一致
2、实现多线程的3种方法
第一种方法:继承Thread类,重写run方法(了解即可)
实现代码如下:
//创建多线程方式一:继承Thread类,重写run方法,调用start方法开启线程
public class TestThread1 extends Thread{
@Override
public void run(){
for (int i = 0; i < 1000; i++) {
System.out.println("看代码--"+i);
}
}
public static void main(String[] args) {
//main线程,主线程
//创建线程对象,并调用start()方法启动线程
TestThread1 thread1 = new TestThread1();
thread1.start();
for (int i = 0; i < 1000; i++) {
System.out.println("学习多线程--"+i);
}
}
}
第二种方法:实现Runnable接口,重写run方法(重点)
实现代码如下:
//创建多线程方式二:实现Runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法
public class TestThread2 implements Runnable{
@Override
public void run(){
for (int i = 0; i < 1000; i++) {
System.out.println("看代码--"+i);
}
}
public static void main(String[] args) {
//main线程,主线程
//创建Runnable接口的实现类对象
TestThread2 testThread2 = new TestThread2();
//创建线程对象,通过线程对象来开启我们的线程,代理
Thread thread = new Thread(testThread2);
thread.start();
for (int i = 0; i < 1000; i++) {
System.out.println("学习多线程--"+i);
}
}
}
第三种方法:实现Callable接口(了解即可)
实现Callable接口,需要返回值类型
重写call方法,需要抛出异常
创建目标对象
创建执行服务:ExecutorService ser = Executors.newFixedThreadPool(1);
提交执行:Futureresult1 = ser.submit(t1);
获取结果:boolean r1 = result1.get()
关闭服务:ser.shutdownNow();
代码练习–龟兔赛跑:
//模拟龟兔赛跑
public class Race implements Runnable{
//定义胜利者
private static String winner;
@Override
public void run() {
for (int i = 0; i <= 100; i++) {
//模拟兔子休息。每隔10毫秒
if (Thread.currentThread().getName().equals("兔子") && i%10==0){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//判断比赛是否结束
boolean flag = gameOver(i);
if(flag)
break;
System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
}
}
//判断是否完成比赛
private boolean gameOver(int steps){
if(winner != null) //已经有winner了
return true;
if(steps == 100){
winner = Thread.currentThread().getName();
System.out.println("winner is "+ winner);
return true;
}
return false;
}
public static void main(String[] args) {
Race race = new Race();
new Thread(race,"兔子").start();
new Thread(race,"乌龟").start();
}
}
3、线程方法
setPriority(int newPriority)
更改线程优先级
static void sleep(long millis)
让当前正在执行的线程休眠指定的毫秒数
void join()
等待该线程终止
static void yield()
暂停当前正在执行的线程对象,并执行其他线程
void interrupt()
中断线程,别用这个
boolean isAlive()
测试线程是否处于活动状态
测试线程优先级(priority)
根据多次运行结果:main线程每次是都是最先运行。而另外3个,随机
可知:main线程优先级是5,不设置(默认)也是5。优先级低只是被调用的概率低, 并不是优先级低就不会被调用了,这都要看CPU的调度。
代码练习:
package com.lu.state;
//测试线程优先级
//根据多次运行结果:main线程每次是都是最先运行。而另外3个,随机
//可知:main线程优先级是5,不设置(默认)也是5。优先级低只是被调用的概率低,
//并不是优先级低就不会被调用了,这都要看CPU的调度
public class TestPriority{
public static void main(String[] args) {
//主线程默认优先级
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
MyPriority myPriority = new MyPriority();
Thread t0 = new Thread(myPriority);
Thread t1 = new Thread(myPriority);
Thread t2 = new Thread(myPriority);
//先设置优先级在启动
t1.setPriority(1);
t2.setPriority(10);
t1.start();
t2.start();
t0.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
}
}
守护(daemon)线程
线程分为用户线程和守护线程
虚拟机必须确保用户线程执行完毕
虚拟机不用等待守护线程执行完毕
如,后台记录操作日志,监控内存,垃圾回收等待
代码练习:
package com.lu.state;
//测试守护线程
//上帝守护你
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true);//默认是false,表示是用户线程,正常的线程都是用户线程...
thread.start();//上帝守护线程启动
new Thread(you).start();//你,用户线程启动
}
}
//上帝
class God implements Runnable{
@Override
public void run() {
while (true){
System.out.println("上帝保佑着你");
}
}
}
//你
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("你一生都开心的活着");
}
System.out.println("goodbye world!");
}
}
转载:https://blog.csdn.net/qq_42524288/article/details/105783409