多线程【Thread、线程创建】

主线程:执行主方法的线程,就叫做主线程

单线程程序:程序从mani开始从上到下依次运行

程序从main方法开始运行,JVM运行main方法,会找操作系统
开辟一条通向cpu的执行路径,cpu可以通过这条路径来执行main方法
这条路径有一个名字叫主(main)线程

创建线程方式一继承Thread类
实现步骤:
1.创建Thread类的子类
2.重写Thread类中的run方法,设置线程的任务
3.创建Thread类的子类对象
4.调用Thread类中的start方法开启一个新的线程,执行run方法
使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
结果是两个线程并发地运行;当前线程(main线程)和另一个线程(执行 run 方法的线程)。
多次启动一个线程是非法的。特别是当线程已经结束执行后,不能再重新启动。

打印的结果出现了随机性:
开启两个线程,对于cpu就选择权利
喜欢谁,就执行谁,所以就出现了随机性结果

 1 public class MyThread extends Thread{
 2     /*
 3      * 2.重写Thread类中的run方法,设置线程的任务
 4      * 开启这个线程要干什么事情
 5      */
 6     @Override
 7     public void run() {
 8         for (int i = 0; i < 50; i++) {
 9             System.out.println("run..."+i);
10         }
11     }
12 }
13     public static void main(String[] args) {
14         //3.创建Thread类的子类对象
15         MyThread mt = new MyThread();
16         //mt.run();//不会开启线程,还是单线程程序
17         //4.调用Thread类中的start方法开启一个新的线程,执行run方法
18         mt.start();
19
20         new MyThread().start();
21
22         for (int i = 0; i < 50; i++) {
23             System.out.println("main..."+i);
24         }
25     }

线程的名称:
主线程:"main"
开启的其它线程的名称:"Thread-0","Thread-1"....

获取线程的名称
1.Thread类中的方法getName
String getName() 返回该线程的名称。
2.Thread类中的静态方法,获取当前正在执行的线程
static Thread currentThread() 返回对当前正在执行的线程对象的引用。
设置线程的名称:
1.Thread类中的方法setName(String name)
void setName(String name) 改变线程名称,使之与参数 name 相同。
2.子类添加带参构造,调用父类Thread类的带参构造方法,传递线程的名称,让父类给线程起名字(让父亲给儿子起名字)
Thread(String name) 分配新的 Thread 对象。

创建线程方式—实现Runnable接口

实现步骤:
1.创建Runnable接口的实现类
2.重写Runnable接口中的run方法,设置线程任务
3.创建Runnable接口的实现类对象
4.创建Thread类对象,构造方法中传入Runnable接口的实现类
Thread(Runnable target) 分配新的 Thread 对象。
5.调用Thread类中的方法start,开启线程执行run方法

实现Runnable的好处
1.避免了类继承Thread类之后,无法继承其它的类(单继承的局限性)
2.把设置线程任务,和开启线程进行解耦,增强了扩展性
实现类的作用:就是设置线程任务
Thread类的作用:开启线程
好处:传递不同的实现类,实现类重写的方法不一样,可以调用不同的方法

线程的匿名内部类使用

匿名:没有名字
内部类:写在其他类内部的类(成员位置:成员内部类,局部位置(方法中):局部内部类)

匿名内部类的格式:
new 父类/接口(){
重写父类/接口中的方法;
};

多线程的父类:
Thread
Runnable

1  new Thread(){
2             //重写run方法,设置线程任务
3             @Override
4             public void run() {
5                 for (int i = 0; i < 20; i++) {
6                     System.out.println(Thread.currentThread().getName()+":"+i);
7                 }
8             }
9         }

以上一堆代码就是一个创建子类重写父类方法的过程
相当于: new MyThread().start();

程序出现了线程安全问题:卖了重复的票和不存在的票

解决方案:
第一种方式:可以使用同步代码块

synchronized(锁对象){
产生安全问题的代码;
访问了共享数据的代码;
}

注意:
必须要保证多个线程使用的是同一个锁对象
//在成员位置上创建一个锁对象(保证唯一)

 1 Object obj = new Object();
 2
 3     @Override
 4     public void run() {
 5         //让卖票重复执行
 6         while(true){
 7
 8              * 同步代码块
 9              * 程序会频繁的判断锁,获取锁,释放锁,所以会降低速度
10
11             synchronized (obj) {
12                 if(ticket>0){
13                     //为了提高安全问题的概率,让程序睡眠
14                     try {
15                         Thread.sleep(10);
16                     } catch (InterruptedException e) {
17                         e.printStackTrace();
18                     }
19                     //卖票ticket--
20                     System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票");
21                 }
22             }
23         }
24     }

程序出现了线程安全问题:卖了重复的票和不存在的票

解决方案:
第二种方式:同步方法

使用步骤:
1.把可能出现安全问题的代码抽取到一个方法中
2.把方法增加一个关键字synchronized
修饰符 synchronized 返回值类型 方法名(参数){
可能出现安全问题的代码;
访问了共享数据的代码;
}

同步方法使用的锁对象是什么?
使用的就是本类对象new RunnableImpl()-->叫this

静态的同步方法,使用时什么锁对象?
使用的是本类对象的class属性(反射)
RunnableImpl.class

 1 *@Override
 2     public void run() {
 3         //让卖票重复执行
 4         while(true){
 5             payTicket2();
 6         }
 7     }
 8
 9
10      * 静态的同步方法
11
12     public static synchronized void payTicket2(){
13         synchronized (RunnableImpl.class) {
14             if(ticket>0){
15                 //为了提高安全问题的概率,让程序睡眠
16                 try {
17                     Thread.sleep(10);
18                 } catch (InterruptedException e) {
19                     e.printStackTrace();
20                 }
21                 //卖票ticket--
22                 System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票");
23             }
24         }
25     }
26
27
28
29      * 抽取出一个同步方法
30      * 快捷键:alt+shift+m
31
32     public ynchronized void payTicket1() {
33         synchronized (this) {
34             //System.out.println(this);//[email protected]
35             if(ticket>0){
36                 //为了提高安全问题的概率,让程序睡眠
37                 try {
38                     Thread.sleep(10);
39                 } catch (InterruptedException e) {
40                     e.printStackTrace();
41                 }
42                 //卖票ticket--
43                 System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票");
44             }
45         }
46     }

程序出现了线程安全问题:卖了重复的票和不存在的票
*
* 解决方案:
* 第三种方式:使用Lock接口,JDK1.5之后出现的
*
* java.util.concurrent.locks.Lock接口
* 方法:
* void lock() 获取锁。
* void unlock() 释放锁。
* 接口的实现类:ReentrantLock
*
* 实现步骤:
* 1.在成员位置创建一个Lock接口的实现类对象ReentrantLock
* 2.在可能出现线程安全问题的代码前,调用lock方法获取锁
* 3.在可能出现线程安全问题的代码后,调用unlock方法释放锁
*
*1.在成员位置创建一个Lock接口的实现类对象ReentrantLock
Lock l = new ReentrantLock();

 1 @Override
 2     public void run() {
 3         //让卖票重复执行
 4         while(true){
 5             //2.在可能出现线程安全问题的代码前,调用lock方法获取锁
 6             l.lock();
 7                 if(ticket>0){
 8                     //为了提高安全问题的概率,让程序睡眠
 9                     try {
10                         Thread.sleep(10);
11                         //卖票ticket--
12                         System.out.println(Thread.currentThread().getName()+"...卖第"+ticket--+"张票");
13                     } catch (InterruptedException e) {
14                         e.printStackTrace();
15                     }finally {
16                         //3.在可能出现线程安全问题的代码后,调用unlock方法释放锁
17                         l.unlock();
18                     }
19                 }
20         }
时间: 2024-10-16 03:39:11

多线程【Thread、线程创建】的相关文章

Java基础加强之多线程篇(线程创建与终止、互斥、通信、本地变量)

线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public class Thread implements Runnable { /* What will be run. */ private Runnable target; ...... /** * Causes this thread to begin execution; the Java Virtu

Java多线程之线程创建

一.程序.进程与线程的理解: 1.程序(program): 是为完成特定任务.用某种语言编写的一组指令的集合.即指一段静态的代码,静态对象. 2.进程(process): 是程序的一次执行过程, 或是正在运行的一个程序.是一个动态的过程:有它自身的产生.存在和消亡的过程,即生命周期.(1)例如:运行中的QQ,运行中的MP3播放器.(2)程序是静态的,进程是动态的.(3)进程作为资源分配的单位,系统在运行时会为每个进程分配不同的内存区域. 3.线程(thread): 进程可进一步细化为线程,是一个

Java多线程Thread的创建

Java中线程的创建有两种方式: 1.  通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中 2.  通过实现Runnable接口,实例化Thread类 第一种方式:继承Thread类 package com.yyx.thread; /** * 通过继承Thread类创建线程 * yyx 2018年2月4日 */ public class CreateThreadByextends { public static void main(String[] args)

Java多线程系列-线程创建

1.怎样创建多线程? Java从语言级别实现多线程,因此实现一个多线程程序很easy.有两种方法能够实现多线程,即继承Thread类和实现Runnable接口.由于Java不支持多继承的原因,建议尽可能通过实现Runnable接口实现多线程. 使用Runnable接口实现多线程有例如以下长处: 1.能够避免由于Java的单继承特性而带来的局限. 2.增强程序的健壮性.代码能够被多个线程共享.代码与数据是独立的: 3.适合多个同样程序代码的线程区处理同一资源的情况. 两者之间的不同: *Threa

Python多线程之线程创建和终止

python主要是通过thread和threading这两个模块来实现多线程支持.python的thread模块是比较底层的模块,python的threading模块是对thread做了一些封装,可以更加方便的被使用.但是python(cpython)由于GIL的存在无法使用threading充分利用CPU资源,如果想充分发挥多核CPU的计算能力需要使用multiprocessing模块. 如果在对线程应用有较高的要求时可以考虑使用Stackless Python来完成.Stackless Py

多线程 Thread 线程同步 synchronized

1.多线程基础以及两种启用方式 /** * 多线程 * 多线程改变了代码的执行方式,从原有的所有代码都串行操作改变为多个代码片段之间并行操作. * 因此多线程允许多个代码片段"同时运行". * * 创建线程的方式有两种 * 1:继承线程并重写run方法,在run方法中定义线程要执行的任务. */ public class ThreadDemo1 { public static void main(String[] args) { Thread t1 = new MyThread1();

Java多线程Thread线程安全

1.什么是线程安全问题? 从某个线程开始访问到访问结束的整个过程,如果有一个访问对象被其他线程修改,那么对于当前线程而言就发生了线程安全问题: 如果在整个访问过程中,无一对象被其他线程修改,就是线程安全的. 2.线程安全问题产生的根本原因 首先是多线程环境,即同时存在有多个操作者,单线程环境不存在线程安全问题.在单线程环境下,任何操作包括修改操作都是操作者自己发出的, 操作者发出操作时不仅有明确的目的,而且意识到操作的影响. 多个操作者(线程)必须操作同一个对象,只有多个操作者同时操作一个对象,

Java 线程第三版 第一章Thread导论、 第二章Thread的创建与管理读书笔记

第一章 Thread导论 为何要用Thread ? 非阻塞I/O I/O多路技术 轮询(polling) 信号 警告(Alarm)和定时器(Timer) 独立的任务(Task) 并行算法 第二章 Thread的创建与管理 一.什么是Thread ? Thread是所在主机执行的应用程序任务(task). 只有一个线程的例子: public class Factorial { public static void main(String[] args) { int n = 5; System.ou

Java多线程01(Thread类、线程创建、线程池)

Java多线程(Thread类.线程创建.线程池) 第一章 多线程 1.1 多线程介绍 1.1.1 基本概念 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程.一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序. 简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 1.1.2 单线程程序 - 从入口m