线程的基础知识梳理

1、线程与进程的:

  1. 进程:
    • 运行中的应用程序,没有运行的程序不算进程
    • 进程是Cpu分配资源的最小单位。
    • 单核的CPU任何时间点上都只能运行一个进程
  2. 线程
    • 轻量级的进程
    • 程序中的一个控制流程,也是CPU的基本调度单位
    • 进程可以由单个或者多个线程组成,彼此间完成不同的工作,交替执行,称为多线程
    • JVM虚拟机是一个进程,默认的包含主线程(main函数),可以通过代码创建多个独立的线程,与main线程并发执行
  3. 线程的组成:
    • 时间片,由Cpu分配的执行时间
    • 运行的数据
      • 堆空间:存储线程需要使用的对象,多个线程可以共享堆中的对象
      • 栈空间:存储线程需要使用局部变量,每个线程都拥有独立的栈、
  4. 多线程:
    • 宏观并行,微观串行

2、自定义线程

需要继承Thread或者实现Runnable

  1. 线程的创建

    • 继承Thread类
    • 实现Runnable接口
    • 他们都需要重写run方法。run方法里面就是调用该线程时需要完成的功能
  2. 两种方法的区别

    • 第一种方法,可以直接进行对线程的操作,即new出来的对象就是一个线程、代码相比较简单一些,但是只适用于单继承。
    • 第二种方法, new出的对象还不是线程,需要创建一个线程,然后把这个对象作为参数创建线程。
    • 第二种实现接口的方法,能够实现对象资源的共享
    class Test extends Thread {
        public void run(){
            System.out.println("线程名:" + Thread.curreantThread().getName());
        }
        public static void main(String[] args){
    		Test t = new Test();
            t.start();
        }
    }  
    
  3. 线程的命名:

    • 对于继承Thread类的线程,可以在构造方法中,调用父类的构造方法,传入线程名。

    • 对于实现Runnable接口的类,因为接口中没有构造方法,因此不能使用上面的方法,但是可以在声明线程的时候,加上线程名。

    • 他们都能调用setName()方法改变线程名

      public class Test extends Thread{
      	private String name ;
      	public Test(String name) {
      		super(name);
      	}
      	public void run() {
      		System.out.println(Thread.currentThread().getName());
      	}
      	public static void main(String[] args) {
      		Test t1 = new Test("线程A");
      		Test2 test2  = new Test2();
      		Thread t2 = new Thread(test2 , "线程B") ;
      //		t1.start();
      		t2.start();
      		
      		t1.setName("改变");
      		t1.start();
      	}
      }
      
      class Test2 implements Runnable{
      	public void run() {
      		System.out.println(Thread.currentThread().getName());
      	}
      }
      
  4. 调用start()方法与直接调用run()方法的区别

    • 调用start()方法,代表了启动一个线程
    • 直接调用run()方法,代表的只是单独的调用了run()方法;
  5. 线程的优先级Priority

    • 分为10级1~10,数字越大级别越高,但是优先级知识代表了获得时间片的概率。
    • getPriority()获得该线程的优先级
    • setPriority()改变线程的优先级
  6. 线程的常用方法

    • void setName(String name) 更改线程的名字
    • void setPriority(int newPriority) 更改线程的优先级
    • static void sleep(long millis) 线程进入睡眠状态millis时间
    • void join() 插队,谁调用它,谁先执行
    • static void yield() 礼让,主动的放弃时间片,回到就绪状态,竞争下一次的时间片,可能会继续抢到时间片。
    • void interrupt() 中断,只是添加一个中断标记,不会立刻停止
    • boolean isAlive() 判断线程是否死亡,以弃用
  7. 线程的状态

    • 初始状态:线程对象被创建,只在堆空间中开辟了内存,与常规的对象一样
    • 就绪状态:调用start()方法,进入就绪状态,等待os选中,并且分配时间片
    • 运行状态:获得时间片之后,进入运行状态,如果时间片到期,则回到就绪状态。
    • 终止状态:主线程或者独立的线程结束,进入终止状态,并且释放所有的时间片
    • 阻塞状态:就是其他的线程抢到了同步锁的控制权,其他线程进入阻塞状态。
  8. 线程的同步

    • 每一个线程,就拥有一个独立的run方法,因此当一个run方法被return终止的时候,不会因此结束别的线程。

    • 关键字synchronized 有两个适用场景

      • 对代码块进行加锁
      • 对方法进行加锁
    • synchronized关键字, ),运行到这个方法时,都要检查有没有其它线程B(或者C、 D等)正在用这个方法(或者该类的其他同步方法),有的话要等正在使用synchronized方法的线程B(或者C 、D)运行完这个方法后再运行此线程A,没有的话,锁定调用者,然后直接运行。

    • 当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定

      public class RunThread implements Runnable{
      	int length = 1000 ;
      	public void run() {
      		for(int i = 0 ; i <= 1000 ; i += 100) {
      			if(length == 0 ) {
      				break;
      			}
      			synchronized (this) {
      				for(int j = 0 ; j <= 100 ; j += 10) {
      					try {
      						Thread.sleep(100);
      					} catch (InterruptedException e) {
      						e.printStackTrace();
      					}
                       System.out.println(Thread.currentThread().getName() + "跑了十米");
      				}
      				length = length - 100 ;
      				System.out.println(Thread.currentThread().getName() + "跑了一百米 ,换下一人");
      				System.out.println("还剩下:" + (length) +"米");
      				return ;
      			}
      		}
      public class Test {
      	public static void main(String[] args) {
      		RunThread r = new RunThread();
      		
      		Thread t1 = new Thread(r,"1号" );
      		Thread t2 = new Thread(r,"2号" );
      		Thread t3 = new Thread(r,"3号" );
      		Thread t4 = new Thread(r,"4号" );
      		Thread t5 = new Thread(r,"5号" );
      		Thread t6 = new Thread(r,"6号" );
      		Thread t7 = new Thread(r,"7号" );  
      		Thread t8 = new Thread(r,"8号" );
      		Thread t9 = new Thread(r,"9号" );
      		Thread t10 = new Thread(r,"10号" );
      		
      		t1.start();
      		t2.start();
      		t3.start();
      		t4.start();
      		t5.start();
      		t6.start();
      		t7.start();
      		t8.start();
      		t9.start();
      		t10.start();
      	}
      }
      

3、生产者,消费者的问题

主要涉及到是两个Object之中的方法:

void wite(); 使线程进入等待的状态,直到线程被唤醒

void notfiy(); 唤醒线程 ,是随机唤醒

public class Com {
	private String host ;//主机
	private String display ;// 显示器
	List<Com> list = new ArrayList<Com>();
	public String getHost() {
		return host;
	}
	public void setHost(String host) {
		this.host = host;
	}
	public String getDisplay() {
		return display;
	}
	public void setDisplay(String display) {
		this.display = display;
	}
	
	public Com(String host , String display) {
		this.host = host ;
		this.display = display ;
	}
	public Com () {}

	public String toString() {
		return "这个电脑是:[主机是:" + host + "=== 显示器是:" + display  + "]";
	}
}

public class Consumer implements Runnable{
	private Com com = null ;
	public Com getCom() {
		return com;
	}
	public Consumer(Com com) {
		this.com = com;
	}
	public void run() {
		for(int i = 0 ; i <= 100 ; i++) {
			synchronized(com) {
				if(com.list.size() <= 0 ) {
					com.notify();
					try {
						com.wait();
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}else {
					for(int j = 4 ; j >= 0 ; j--)
					System.out.println(com.list.remove(j));
				}
			}
		}
	}
}

public class Pro implements Runnable{
	private Com com = null ;

	public Com getCom() {
		return com;
	}
	public Pro(Com com) {
		this.com = com;
	}
	public void run() {ynchronized (com) {
				for(int i = 1 ; i <= 100; i++) {
				if(com.list.size() >= 5) {
					com.notify();
					try {
						com.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}else {
					if (i % 2 == 0) {
						com.list.add(new Com("华硕" + i,"联想" + i + "号"));
					}else {
						com.list.add(new Com("泰坦" + i,"泰泰" + i + "号"));
					}
				}
			}
		}
	}
}

public class Supermarket {
	public static void main(String[] args) {
		Com com = new Com() ;
		Pro pro = new Pro(com);
		Consumer con = new Consumer(com);
		
		Thread t1 = new Thread(pro);
		Thread t2 = new Thread(con);
		
		t1.start();
		t2.start();
	}
}
<think>首先,用户的问题是:“我想获取Java线程基础知识列表 请问Java线程基础知识详解”。这表示用户想要一个关于Java线程基础知识的详细列表。 根据系统级指令: - 所有行内数学表达式必须使用$...$格式,但在这个上下文中,Java线程可能不涉及数学表达式,所以我可以忽略这一点,除非有需要。 - 独立公式必须使用$$...$$格式,但同样,可能不适用。 - LaTeX语法正确:确保任何数学表达式正确。 - 使用中文回答:整个回答必须用中文。 - 生成相关问题:在回答末尾生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识:例如[^1]。我需要引用提供的引用内容。 用户提供的引用: - 引用[1]:关于Java线程基础知识,包括一个线程实现类的代码示例。 - 引用[2]:Java线程基础知识总结,列出了线程状态、创建方式、线程安全、同步、死锁、控制线程方法、线程通信等。 用户的问题是基于这些引用获取Java线程基础知识列表。所以,我应该整合这些信息,提供一个结构化的列表。 回答结构: - 由于用户要求“基础知识列表”,我应该以列表形式呈现。 - 回答结构清晰,帮助用户逐步解决问题。 - 尽量保证回答真实可靠:基于提供的引用和一般知识。 步骤: 1. **介绍**:简要介绍Java线程基础知识。 2. **主体**:列出基础知识点,基于引用[2]的内容,因为它更总结性。 - 线程的状态 - 创建线程的方式 - 线程安全问题 - 线程同步(synchronized, Lock) - 死锁 - 控制线程的方法(start, sleep, yield, join, setPriority, 后台线程) - 线程通信(wait, notify, notifyAll, Condition, volatile) - 引用[1]提供了代码示例,我可以引用它。 3. **添加引用**:在相关部分末尾添加引用标识,如[^1]或[^2]。 4. **代码示例**:如果适用,可以包括代码,但用户要求列表,所以可能简要提及。 5. **相关问题**:在末尾生成相关问题。 生成相关问题: - 基于主题,生成2-3个相关问题,如: 1. Java线程的生命周期是怎样的? 2. 如何避免线程死锁? 3. Java线程池的使用方法? 确保引用自然添加: - 例如,当讨论线程同步时,提到引用中的synchronized关键字,并添加[^1]或[^2]。 完整回答结构: - 开头:解释Java线程基础知识。 - 主体:使用列表格式(如有序或无序列表)列出知识点。 - 结尾:生成相关问题。 最终输出格式: - 用户可见层:回答结构清晰。 - 在末尾添加“§§相关问题§§”部分。</think>### Java线程基础知识详解 Java线程Java编程的核心概念之一,它允许程序同时执行多个任务,提高应用程序的性能和响应能力。以下是一个结构化的Java线程基础知识列表,基于权威资料和最佳实践整理而成。内容涵盖线程的基本概念、创建方式、状态管理、同步机制、通信方法等关键点。每个知识点都简要解释,并附上相关代码示例或引用,确保清晰易懂。 #### Java线程基础知识列表 1. **线程的状态** Java线程有6种生命周期状态,定义在`Thread.State`枚举中: - `NEW`:线程已创建但未启动。 - `RUNNABLE`:线程正在运行或准备运行(包括就绪状态)。 - `BLOCKED`:线程被阻塞,等待获取监视器锁(例如,在`synchronized`块中)。 - `WAITING`:线程无限期等待,直到被其他线程唤醒(通过`notify()`或`notifyAll()`)。 - `TIMED_WAITING`:线程在指定时间内等待(例如,通过`sleep(millis)`或`join(millis)`)。 - `TERMINATED`:线程已执行完毕。 *引用来源:Java线程基础知识总结[^2]。* 2. **创建线程的方式** Java提供两种主要方式创建线程: - **继承`Thread`类**:重写`run()`方法,直接调用`start()`启动线程。 示例代码(基于引用[1]): ```java public class Thread1 extends Thread { public Thread1(String name) { super(name); // 给线程名字赋值 } static int i = 10; static Object ob = "lock"; // 静态锁对象 @Override public void run() { while (i > 0) { synchronized (ob) { // 使用synchronized同步 if (i > 0) { System.out.println(getName() + "线程调用还有" + i + "次"); i--; } } try { sleep(1000); // 线程休眠1秒 } catch (InterruptedException e) { e.printStackTrace(); } } } } ``` - **实现`Runnable`接口**:定义`run()`方法,将`Runnable`对象传递给`Thread`构造函数。 优点:避免单继承限制,更灵活。 *引用来源:Java线程基础知识详解[^1]。* 3. **线程安全问题** 当多个线程访问共享资源时,可能导致数据不一致(如计数器错误)。常见原因包括: - 竞态条件(Race Condition):多个线程同时修改数据。 - 内存可见性问题:一个线程修改数据后,其他线程未及时看到变化。 解决方案:使用同步机制(如`synchronized`或`Lock`)。 4. **线程同步** 确保多线程安全访问共享资源: - **synchronized关键字**:修饰方法或代码块,提供互斥锁。示例:`synchronized(ob) {...}`(见上述代码)[^1]。 - **Lock接口**:更灵活的锁机制,如`ReentrantLock`,支持尝试锁、公平锁等。 - **ReadWriteLock接口**:优化读写分离,允许多个读线程同时访问。 *引用来源:Java线程基础知识总结[^2]。* 5. **死锁** 当多个线程相互等待对方释放锁时,程序永久阻塞。常见场景: - 线程A持有锁X,等待锁Y;线程B持有锁Y,等待锁X。 避免方法:使用锁顺序、超时机制(如`tryLock(timeout)`)或死锁检测。 6. **控制线程的方法** Java提供以下方法管理线程行为: - `start()`:启动线程,进入RUNNABLE状态。 - `sleep(long millis)`:让当前线程休眠指定毫秒,释放CPU但不释放锁。 - `yield()`:提示线程让出CPU,但不保证其他线程立即运行。 - `join()`:等待目标线程结束(例如,主线程等待子线程完成)。 - `setPriority(int priority)`:设置线程优先级(1-10),但依赖操作系统调度。 - 后台线程(Daemon Thread):通过`setDaemon(true)`设置,当所有非后台线程结束时自动终止(常用于守护任务)。 *引用来源:Java线程基础知识总结[^2]。* 7. **线程通信** 实现线程间协调: - **传统方法**(基于`Object`类): - `wait()`:释放锁,让线程进入WAITING状态。 - `notify()`/`notifyAll()`:唤醒等待的线程。 经典案例:生产者-消费者模型(使用共享缓冲区)[^2]。 - **Condition接口**:与`Lock`配合使用,提供更精细的等待/唤醒控制(如`await()`和`signal()`)。 - **volatile关键字**:确保变量修改对其他线程立即可见,避免内存可见性问题(但不保证原子性)。 *引用来源:Java线程基础知识总结[^2]。* #### 总结 Java线程基础知识包括状态管理、创建方式、同步机制、通信方法等核心点。掌握这些是编写高效、安全并发程序的基础。实际开发中,建议优先使用`Runnable`接口和`Lock`机制,以提高灵活性和性能。如果遇到具体问题,可参考Java官方文档或相关教程深入实践。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值