线程的创建方法和介绍
一个进程对应多个线程
可以充分发挥COP性能的一个东西,一个进程至少有一个线程
cpu 如何处理线程:单位时间片上高速的切换线程,并且一个单核的cpu值能处 理一个线程
cpu的处理最小单位是线程,线程获取cpu的机会是一样的
线程将一个独立的任务.包装成一块代码块,交给cpu 处理
cpu决定分配资源给谁:线程的执行由cpu决定
代码执行流程由cpu决定
如果执行多个线程:
看到的效果: 两个任务不规则的交替执行:
Threa类: Java中的线程类
run: 线程的线程体
需要包装任务,需要独立执行的代码块,
start: 启动线程的方法,告诉cpu,我准备好了.
第一种方法创建线程,继承Threa类,:
覆写run方法
要写几个类,根据功能的数量决定,定义线程类的数量
根据确定的功能,覆写run方法
创建线程对象,
调用start方法,启动线程
实例: 利用线程多个下载
cpu处理线程不一定马上分配资源,因为计算机有很多线程
期望看到的效果:交替不规则
public class Thread_2 extends Thread { //继承Thread类
private String name; //设一个字段
Thread_2(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(name+"下载了" + i + "%");
}
}
}
测试:
public class Thread_1 {
public static void main(String[] args) {
System.out.println("打印一个单线程");
Thread_2 thread_2=new Thread_2("金牌梅"); //启动线程的对象
//thread_2.run();//只是调用方法而已,并不是线程
thread_2.start(); //start 启动线程
Thread_2 thread_21=new Thread_2("斗罗");
thread_21.start(); //和第一个start交替
}
}
斗罗下载了70%
金牌梅下载了81%
斗罗下载了71%
金牌梅下载了82%
斗罗下载了72%
金牌梅下载了83%
斗罗下载了73%
金牌梅下载了84%
斗罗下载了74%
金牌梅下载了85%
斗罗下载了75%
斗罗下载了76%
金牌梅下载了86%
斗罗下载了77%
金牌梅下载了87%
斗罗下载了78%
金牌梅下载了88%
斗罗下载了79%
金牌梅下载了89%
斗罗下载了80%
斗罗下载了81%
交替不规则的效果
线程run方法作为线程的线程,必须覆写run方法:
上面方法还是不够完善,存在线程安全问题:
创建一个锁对象,可以被多个线程共享,相当于一个共享锁’
Object obj=new Object();
调用synchronized (obj) { 需要锁的数据 }
代码演示:
class Tic extends Thread {
private static String name;
static int tickets = 100; //继承的字段,要共享.加static
staic Object obj = new Object(); //创建一个锁对象,可以被多个线程共享的的数据 ,必须共享锁
public Tic(String name) { //父类Thread也可以继承父类的( (String name)
this.name = name;
//super(name);直接调用父类的
}
@Override //必须覆写方法
public void run() {
while (true) {
synchronized (obj) {
if (tickets > 0) {
System.out.println(name + "卖出的座位是" + tickets--);
} else {
break;
}
}
try {
Thread.sleep(100); //休眠时间 .自定义异常
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(name + "票已经买完"); //
}
}
调用start和调用run的区别;
调用start方法,就是启动一个线程,
线程一旦启动,就谁也管不了,只能由cpu分配. (每个线程都是独立的)
run方法里面只是一个普通方法;
run只是一个普通方法,也可以对象直接调用,
如果想要字段是共享的,字段必须static修饰,如果调用的是Runnable接口,
不需要用static 都是共享的,调用的就是一个线程对象,在Thread对象中去调用.
线程的第二种创建方式: 实现Runnable接口
run方法其实算是Runnable接口的,Thread也只不过调用,但是Runnable没有启动方法static的,所有使用接口覆写run方法还得启动,就只有new Thread对象作为一个可以放Runnable的壳.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jLiQTleL-1616227251595)(C:\Users\ljl\AppData\Local\Temp\1555909743633.png)]
首先看看下面的图解,
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sqmxjTwf-1616227251596)(C:\Users\ljl\AppData\Local\Temp\1555904503817.png)]
代码详解:
class Runnable_11 implements Runnable {
//String name;
int num = 100;
/* Runnable_11(String name){
this.name=name;
}*/
@Override
public void run() {
while (num > 0) {
if (num > 0) {
System.out.println( "打印" + num);
num--;
}else {
break;
}
}
}
}
测试:
public class Runnable_1 {
public static void main(String[] args) {
Runnable_11 runnable_11 = new Runnable_11();
Thread thread1 = new Thread(runnable_11,"第一");
Thread thread2 = new Thread(runnable_11,"第二");
Thread thread3 = new Thread(runnable_11,"第三");
thread1.start();
thread2.start();
thread3.start();
}
}
代码执行流程是独立的,但是对象是同一个,字段也是同一个,
每个线程访问的都是同个对象,同个字段,
实现的时候,不需要加static,所有字段都共享
继承:每个对象都是独立一份,
继承只能但几次,
接口:只需要创建一个对象,不需要static 就可以让字段共享
可以实现多个接口,
还可以继承想要的类
实现Runnable接口的线程同步
接口的线程同步的对象可以是this ,"" Object,
this表示当前对象,线程实现接口只创建一个对象,所有每次线程的对象都是一个
注
- 同步监听对象保证自身就是同步监听对象 //同步监听的基础条件
- 必须保证多个线程访问的对象都是同一个同步监听对象//同步监听的基础条件
- 同不监听对象可以是任意对象,再上面都满足的情况下
4)this也可以是同步监听对象 (实现接口接口)
5)当前类的字节码对象.class
代码实现:
class Runnable_11 implements Runnable {
//String name;
int num = 100;
@Override
public void run() {
while (num > 0) {
synchronized ("") {
if (num > 0) {
//当前线程对象的引用 .... 获取名字
System.out.println(Thread.currentThread().getName() + "打印" + num);
num--;
}
}
}
}
}
实现接口 写线程名字必须注意的的方法Thread.currentThread().getName():
获取当前线程对象的名字:
//当前线程对象的引用 .... 获取名字
System.out.println(Thread.currentThread().getName() + "打印" + num);
接口和基础的同步对象的区别
代码执行流程是独立的,但是对象是同一个,字段也是同一个,
每个线程访问的都是同个对象,同个字段,
实现的时候,不需要加static,所有字段都共享
继承:每个对象都是独立一份,
继承只能但几次,
接口:只需要创建一个对象,不需要static 就可以让字段共享
可以实现多个接口,
还可以继承想要的类
接口:同步代码块,可以是this 只有一个对象 ,可以" "字符串,
线程休眠
Thread.sleep(): 再指定线程内让线程处于休眠状态,
线程类Thread当中有一个static void sleep(long millis)方法,在指定的毫秒数内让当前正在执行的线程休眠
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ww1TQ7o8-1616227251598)(file:///C:\Users\ljl\AppData\Local\Temp\ksohtml6176\wps1.jpg)]
-
可以做倒计时:代码清单:
Frame f = new Frame(); Label label = new Label("10"); label.setBackground(Color.RED); // 字体对象 Font font = new Font("宋体",Font.BOLD,666); label.setFont(font); label.setAlignment(Label.CENTER); f.add(label); f.setSize(780, 780); f.setLocationRelativeTo(null); f.setVisible(true); for (int i = 10; i >= 0; i--) { label.setText(i+""); Thread.sleep(1000)
2.可以用来模拟网络延迟,