文章目录
失败,是正因你在距成功一步之遥的时候停住了脚步。
1、线程中的进程
// 用户的程序就是一个进程,正在运行的程序,不是正在执行的程序,抢到cpu的执行全才是正在执行的程序。
// 进程的名字就是执行的类的名字
查看java中的进程
C:\Users\85411>jps
567920
593984 Jps
570212 RemoteMavenServer36
592084 Launcher
2、进程中的线程
public class Demo {
public static void main(String[] args) {
// 线程
// currentThread()获取当前运行的线程
Thread thread = Thread.currentThread();
// getName() 用于获取线程的名字
System.out.println(thread.getName());
// main方法运行在main线程中
// 1.Java程序在运行的时候默认就会产生一个进程
// 2.这个进程会有一个主线程
// 3.代码都在主线程中执行
}
}
3、自己的第一个线程
public class Demo {
public static void main(String[] args) {
// 线程
// currentThread()获取当前运行的线程
Thread thread = Thread.currentThread();
// getName() 用于获取线程的名字
System.out.println(thread.getName());
// 创建线程
MyThread t = new MyThread();
// 启动线程
t.start();
}
}
class MyThread extends Thread{
@Override
public void run() {
System.out.println("Thread:"+Thread.currentThread().getName());
}
}
4、线程的生命周期
/**
* NEW :新建
* RUNNABLE :可运行
* BLOCKED :阻塞
* WAITING :等待
* TIMED_WAITING :定时等待
* TERMINATED :终止
*/
5、线程执行方式(串行和并发)
5.1、串行执行
多个线程连接成串,然后按照顺序执行。
public class Demo {
public static void main(String[] args) throws Exception {
// 创建线程
MyThread1 t1 = new MyThread1();
MyThread2 t2 = new MyThread2();
t1.start();
t2.start();
// join()当前线程执行完,在执行其他线程。
t1.join();
t2.join();
// currentThread()获取当前运行的线程
Thread thread = Thread.currentThread();
// getName() 用于获取线程的名字
System.out.println(thread.getName());
}
}
class MyThread1 extends Thread{
@Override
public void run() {
System.out.println("Thread1:"+Thread.currentThread().getName());
}
}
class MyThread2 extends Thread{
@Override
public void run() {
System.out.println("Thread2:"+Thread.currentThread().getName());
}
}
5.2、并发
多个线程是独立,谁抢到CPU的执行权,谁就能执行。
public class Demo {
public static void main(String[] args) {
// 创建线程
MyThread1 t1 = new MyThread1();
MyThread2 t2 = new MyThread2();
t1.start();
t2.start();
// currentThread()获取当前运行的线程
Thread thread = Thread.currentThread();
// getName() 用于获取线程的名字
System.out.println(thread.getName());
}
}
class MyThread1 extends Thread{
@Override
public void run() {
System.out.println("Thread1:"+Thread.currentThread().getName());
}
}
class MyThread2 extends Thread{
@Override
public void run() {
System.out.println("Thread2:"+Thread.currentThread().getName());
}
}
6、线程休眠
public class Demo {
public static void main(String[] args) throws Exception {
// 休眠1秒中,打印一次字符串
while (true) {
Thread.sleep(1000);
System.out.println("main线程执行完毕");
}
}
}
7、工作
public class Demo {
public static void main(String[] args) throws Exception {
// 启动方式一
MyThread1 thread1 = new MyThread1("1");
thread1.start();
// 启动方式二
MyThread2 thread2 = new MyThread2("2");
Thread thread = new Thread(thread2);
thread.start();
// main线程
System.out.println("main线程运行结束");
}
}
// 实现线程方式一
class MyThread1 extends Thread{
private String name;
public MyThread1(String name){
this.name = name;
}
@Override
public void run() {
System.out.println(name+"线程运行结束");
}
}
// 实现线程方式二
class MyThread2 implements Runnable{
private String name;
public MyThread2 (String name){
this.name = name;
}
@Override
public void run() {
System.out.println(name + "线程运行结束");
}
}
8、线程池
public class Demo {
public static void main(String[] args) throws Exception {
// 线程池:现成的容器
// 线程池会根据需要,在启动时,创建一个或多个线程对象
// Java中有4种比较常见的线程池
// 1.创建固定数量的线程对象
//ExecutorService executorService = Executors.newFixedThreadPool(3);
// 2.根据需求动态创建线程
//ExecutorService executorService = Executors.newCachedThreadPool();
// 3.单一线程
//ExecutorService executorService = Executors.newSingleThreadExecutor();
// 4.定时调度线程
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3);
// 开启线程数量
for (int i = 0; i < 5; i++) {
executorService.submit(new MyThread2());
}
}
}
class MyThread2 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程运行结束");
}
}
9、同步
public class Demo {
public static void main(String[] args){
// 多线程访问同步方法时,只能一个一个访问,同步操作
// new Hashtable<>();
// synchronized关键字还可以修饰代码块,称之为同步代码块
/*
synchronized (用于同步对象){
处理逻辑
}
*/
Num num = new Num();
User user = new User(num);
user.start();
Bank bank = new Bank(num);
bank.start();
}
}
class Num{
}
class Bank extends Thread{
private Num num;
public Bank(Num num){
this.num = num;
}
@Override
public void run() {
synchronized (num){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("9:00,开始营业,开始叫号");
num.notifyAll();//唤醒所有等待
}
}
}
class User extends Thread{
private Num num;
public User(Num num){
this.num = num;
}
@Override
public void run() {
synchronized (num){
System.out.println("我是号码1,银行还没开门,我需要等一会");
try {
num.wait();//等待
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("叫到我的号了,该我办业务了");
}
}
}
10、wait和sleep
public class Demo {
public static void main(String[] args){
// 阻塞
// 1.名字
// wait:等待
// sleep:休眠
// 2.从属关系
// wait:Object 成员方法
// sleep:Thread 静态方法
// 3.使用方式
// wait:只能使用在同步代码中
// sleep:可以在任意地方使用
// 4.阻塞时间
// wait:超时时间(会发生错误)
// sleep:休眠时间(不会发生错误)
// 5.同步处理
// wait:执行wait方法,其他线程有机会执行当前的同步操作
// sleep:执行sleep方法,其他线程没有机会执行当前的同步操作
}
}
11、线程安全问题
public class Demo {
public static void main(String[] args){
// 线程安全问题
// 多个线程在并发执行时,修改了共享内存中共享对象的属性,导致的数据冲突问题
User user = new User(); //User是两个线程的共享对象,user.name是共享属性
Thread t1 = new Thread(() ->{
user.name = "zhangsan"; //对共享属性的修改
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(user.name);
});
Thread t2 = new Thread(() ->{
user.name = "lisi"; //对共享属性的修改
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println(user.name);
});
t1.start(); // 将共享属性修改为zhangsan,休眠1秒
t2.start(); // 将共享属性修改为lisi,休眠1秒,这时两个线程打印共享内存中的数据,都是lisi
System.out.println("main线程"); // main不休眠,先执行完毕
}
}
class User{
String name;
}