黑马程序员_Java多线程学习

本文深入探讨Java中线程的创建、线程状态、多线程安全问题及其解决策略,详细解释如何通过继承Thread类或实现Runnable接口创建线程,以及线程之间的同步机制。通过实例演示了线程同步问题的出现与解决方法,包括使用synchronized关键字标记同步代码块或同步函数。

------- android培训java培训、期待与您交流! ----------

一个正在运行完整的Java应用程序实例就是一个进程,在这个应用程序中会保护许多小的执行单元,那么每一个执行单元或控制单元就是一个线程。一个应用程序必须至少有一个线程(主线程)。

一、线程的创建

Java中线程的创建方式有两种:1、继承Thread类实现run方法。通过例子说明创建及启动线程的步骤:

class MyThread extends Thread //1、继承Thread类
{
public MyThread(){}
public void run()//2、实现run方法
{
DoWork();//将要执行的功能
}
public void DoWork(){}
}
class MyThreadDemo
{
public static void main(String[] args)
{
MyThread thread=new MyThread();//3、创建线程子类的对象
thread.start();//4、利用start()函数启动线程,并调用run方法
}
}


注意:该创建方式的一个弊端:因为要创建某线程必须要继承Thread类,而很多情况下一个功能类很可能会继承其他类,Java只支持单继承,那么这个时候就无法再继承Thread类。为了解决这一问题,Java中提供了另外一种创建线程方式,通过实现接口来扩展功能。

2、由于第一中创建线程方式的局限性,第二种方式应运而生——通过实现Runnable接口复写run方法来实现线程的创建。其具体步骤:

class MyFun implements Runnable //1、实现Runnable接口,扩展功能
{
public MyFun(){}
public void run()//2、实现run方法
{
DoWork();//将要执行的功能
}
public void DoWork(){}
}
class MyThreadDemo
{
public static void main(String[] args)
{
MyFun fun=new MyFun();//3、创建MyFun类的对象(注意它不是线程对象)
Thread thread=new Thread(fun);//创建线程对象,并将fun引用作为参数传递给线程的构造函数,与线程建立联系
thread.start();//4、利用start()函数启动线程,并调用run方法
}
}


第二种方式只是对该类进行额外的功能扩展,java就提供了一个接口Runnable并定义了run方法,其实run方法的定义就是为了存储多线程要运行的代码。由于实现Runnable接口可以避免单继承的局限性,所以,通常创建线程都用第二种方式。

二、线程的几种状态。

线程主要有:被创建、运行、冻结(睡眠和等待)、消亡及阻塞等五种状态。

1、线程被创建后通过调用start方法使该线程具有资源的访问资格,同时具备执行权后线程进入运行状态。

2、如果start后该线程拥有了执行资格但是还不具备访问资源的执行权,此时该线程处于临时阻塞状态,当其他线程交出执行权且自己获得执行权后才进入运行状态。

3、对于运行中的线程,可以通过sleep和wait方式将线程进行冻结,对于sleep方式当睡眠时间到,线程自动进入运行状态。而wait方式只能等待别的线程调用notify或notifyAll才能唤醒进入运行状态。各状态之间转换的过程如下图所示:

三、多线程的问题,通常为满足一定的需求,会需要多个线程对同一个资源进行处理,比如一个数据库的写入操作、运算、读取操作等,可能会需要两个以上的线程对这样一个数据库进行处理,那么在线程运行期间会出现数据访问或写入错乱的问题,这就是多线程的安全问题。故未来解决线程安全问题,Java就提供了线程同步机制。

class MulThreaDemo extends Thread
{
private int count=0;
public MulThreaDemo(){}
public void run()
{
for(int i=0;i<10;i++)
{
count += 10;
System.out.println(Thread.currentThread().getName()+"----"+this.count);
Thread.sleep(20);
}
} 
}
class Test
{
MulThreaDemo m1=new MulThreaDemo();
MulThreaDemo m2=new MulThreaDemo();
MulThreaDemo m3=new MulThreaDemo();

m1.start();
m2.start();
m3.start();
}


运行程序我们将会看到m1、m2、m3线程的打印结果是错乱排列的,我本意是要先打印m1结果,然后是m2、m3,这就是由于多个线程同事共享同一个资源造成的,那么,为了解决这个现象,可以利用关键字synchronized来标记同步代码块或同步函数。这个关键字就告诉jvm当前线程拥有访问权,在该线程结束前其他线程不能访问该段代码或函数,此刻其他线程处于等待状态位于线程池中,当线程1执行完后,放弃执行权,那么线程池中等待的线程顺序获得执行权,执行代码。

synchronized的使用方式有两种:同步代码块和同步函数。修饰一个代码块时,synchronized需要指定同步对象,而且保证多线程的同步对象为同一个对象。特殊情况:对于在静态方法内声明同步代码块的地方,在指定同步对象的时候要注意,因为静态方法是在加载类的时候就存在,先于对象引用存在,此时不能再指定所属对象为同步对象,而是要指定为该类的字节码文件对象。

第二种就是同步函数,直接在返回值前添加关键字synchronized(不能放置于返回值的后面)即可。注意同步函数使用的锁对象是this,而同步代码块可以使用任意对象为锁对象。特殊情况是静态方法为同步函数的情况,锁对象不再是this而是该类的字节码文件对象。

eg:

class SynTest
{
public SynTest(){}
//普通方法中指定同步代码块
public void method1()
{
synchronized(this){
//要同步的代码
}
}
//注意是静态方法中同步代码块
public static void method2()
{
synchronized(SynTest.class)
{
//需要同步的代码块
}
}
//普通同步函数
public synchronized void method3(){}
//静态的同步函数
public static synchronized void method4(){}
}

注意:判断线程同步的两个条件:1、必须有两个或两个以上的线程运行。2、多线程必须保证使用的是同一个同步锁(同步对象)。

【直流微电网】径向直流微电网的状态空间建模与线性化:一种耦合DC-DC变换器状态空间平均模型的方法 (Matlab代码实现)内容概要:本文介绍了径向直流微电网的状态空间建模与线性化方法,重点提出了一种基于耦合DC-DC变换器状态空间平均模型的建模策略。该方法通过对系统中多个相互耦合的DC-DC变换器进行统一建模,构建出整个微电网的集中状态空间模型,并在此基础上实施线性化处理,便于后续的小信号分析与稳定性研究。文中详细阐述了建模过程中的关键步骤,包括电路拓扑分析、状态变量选取、平均化处理以及雅可比矩阵的推导,最终通过Matlab代码实现模型仿真验证,展示了该方法在动态响应分析和控制器设计中的有效性。; 适合人群:具备电力电子、自动控制理论基础,熟悉Matlab/Simulink仿真工具,从事微电网、新能源系统建模与控制研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①掌握直流微电网中多变换器系统的统一建模方法;②理解状态空间平均法在非线性电力电子系统中的应用;③实现系统线性化并用于稳定性分析与控制器设计;④通过Matlab代码复现和扩展模型,服务于科研仿真与教学实践。; 阅读建议:建议读者结合Matlab代码逐步理解建模流程,重点关注状态变量的选择与平均化处理的数学推导,同时可尝试修改系统参数或拓扑结构以加深对模型通用性和适应性的理解。
### 关于Java多线程学习笔记 #### 1. 实现多线程的方式 在Java中,可以通过继承`Thread`类或实现`Runnable`接口来创建多线程程序[^1]。 对于通过继承`Thread`类的方法: ```java class MyThread extends Thread { public void run() { System.out.println("MyThread running"); } } ``` 而采用实现`Runnable`接口的形式则更为灵活,因为这不会占用已有的继承机会,并允许共享同一个对象实例给多个线程使用: ```java class MyRunnable implements Runnable { @Override public void run() { System.out.println("MyRunnable running"); } } // 使用方式如下: new Thread(new MyRunnable()).start(); ``` #### 2. 创建并启动线程 一旦定义好了线程体之后,就可以利用`Thread`的构造函数传入该线程体,并调用其`start()`方法开启新线程执行任务。需要注意的是应该避免直接调用`run()`方法,因为它会在当前线程内顺序执行而不是新开一个独立的工作单元。 ```java public class Main { public static void main(String[] args) { Thread thread = new Thread(new MyRunnable()); thread.start(); // 正确做法 // 错误示范:thread.run(); } } ``` #### 3. 线程同步机制 当涉及到资源共享时,可能会遇到竞态条件等问题。为了确保数据一致性,在访问临界区资源前应当加锁保护。可以借助`synchronized`关键字或者更高级别的并发工具包如`ReentrantLock`来进行操作控制。 ```java synchronized (lockObject) { // 对共享变量的操作... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值