在Java中,由于一些需求,需要将某些“程序段”转成并发执行,每一个“程序段”是一个逻辑上相对完整的程序代码段。多线程的主要目的就是讲一个程序中的各个“程序段”并发化。
此时,我们引入多线程的概念,大多程序都是单线程的,即一个程序只有从头到尾执行一次,然而现实中我们可能需要多条途径同事运行,例如,我们可能需要一边听音乐,一边看书,又或是一个游戏中,我们需要boss和hero同时进行攻击等等。而多线程是指在同一个进程中同时存在多个执行体,按几条不同的执行路径同时工作。这正好满足了我们的需要,不是吗?
好了,到这里我就简单的介绍了多线程。线程就像人一样,也是有一个出生,成长再到生命尽头的过程的,这里专业的名词就是所谓的生命周期。线程生命周期图如下:
现在从底层浅谈一下线程调度。调度就是指在各个线程之间分配CPU资源。多个线程并发执行实际上是通过一个调度来进行的。线程调度有两种模型:分时和抢占模型。在分时模型中,CPU资源师按照时间片来分配,获得CPU资源的线程只能在指定的时间片执行,一旦时间片使用完,就必须把CPU让给另一个处于就绪状态的线程。在分时模型中,线程本身不会让出CPU:在抢占模型中,当前活动的线程一旦获得执行权,将一直执行下去,知道执行完或由于某周原因主动放弃执行权。Java语言支持的就是抢占式调度模型,为了使优先级的线程有机会运行,高优先级的线程应该不是地主动进入“睡眠”状态,而暂时让出CPU。
好了,说了这么多题外话,终于进入正题,线程的实现。其实依旧是按照线程的生命周期的过程书写代码。
此处大家需要重点关注的是线程中的run()方法,在主函数中我们调用start()方法的时候会自动执行run()方法,即启动即运行。当然由于我们的每一个Ball类要作为一个线程,所以Ball要继承Thread父类。
public class Ball extends Thread{ private JPanel jf; //半径 private int radius = 20; private int x,y; //x,y方向的速度 private int vx,vy; private Color color; //暂停 private boolean pauseFlag = false; //停止 private boolean stopFlag = false; private Graphics g; //链表队列,保存小球 private ArrayList<Ball> list; public Ball(JPanel jf,ArrayList<Ball> list){ this.list = list; this.jf = jf; Random r = new Random(); //x方向上的速度设为随机 vx = r.nextInt(5)+1; //y方向的速度设为随机 vy = r.nextInt(5)+1; //球的半径 radius = r.nextInt(50)+20; //颜色为随机 color = new Color(r.nextInt(255),r.nextInt(255),r.nextInt(255)); } //设置暂停 public void setPause(boolean flag){ pauseFlag = false; } //设置停止 public void setStop(boolean flag){ stopFlag = flag; } //运行函数 public void run(){ g = jf.getGraphics(); while(true){ //先设置休眠 try { sleep(30); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(pauseFlag == true){ continue; } //清楚上一次的图 //clear(); if(stopFlag) return; //移动 move(); //画画 // draw2(g); } } }
主函数中启动线程:
ActionListener l = new ActionListener(){ public void actionPerformed(ActionEvent e){ if(e.getActionCommand().equals("start")){ //实例化一个小球对象 Ball t = new Ball(jf,list); //启动线程 t.start(); //将小球添加到列队里 list.add(t); } } }
最后,我在介绍几个线程中常用的几个方法。
线程通过多线程的实现貌似就好像动漫人物中的忍术——影分身,同时可以做多个事,但是主线程一般只有一个,就和本体只有一个一样。
相关推荐
使用其他线程修改界面元素可能会导致未知错误,因此需要使用适当的同步机制,如PostMessage或SendDlgItemMessage,从非用户界面线程向用户界面线程发送消息。 四、线程间通信 在MFC中,线程间通信可以通过几种方式...
### MFC多线程的创建详解 #### 一、MFC多线程概述 MFC (Microsoft Foundation Classes) 是微软为简化Windows程序开发提供的一套类库,它封装了Win32 API,使得开发者能够更加方便地进行Windows应用程序的开发。在...
如果一个线程在持有锁的情况下崩溃,其他线程可能会永久阻塞,这被称为死锁。为了避免这种情况,开发者需要谨慎设计锁的使用逻辑,遵循一些最佳实践,如避免嵌套锁,尽可能减少锁的持有时间,以及使用智能指针来自动...
- **信号量(Semaphores)**:限制对资源的并发访问数量,超过限制的线程会被阻塞,直到资源可用。 - **事件(Events)**:通过WaitHandle类的子类(如ManualResetEvent或AutoResetEvent)来同步线程,一个线程等待...
这个过程会消耗CPU时间和内存资源,当线程数量增加时,这些开销会显著增加。 2. **CPU核心限制**:大多数现代计算机都有多个CPU核心,但即便如此,它们也无法无限扩展并发处理能力。当超过物理核心数量时,线程必须...
例如,一个线程可能在执行到特定点时检查一个共享标志,如果该标志指示应暂停,它就会进入等待状态。其他线程可以更改这个标志并通知正在等待的线程继续执行。`Monitor.Pulse`和`Monitor.Wait`是实现这种同步机制的...
如果任务尚未完成,调用`get()`会阻塞当前线程,直到任务完成。 2. **std::promise与std::future** `std::promise`是C++11引入的另一个类,它提供了设置异步任务结果的能力。创建一个`std::promise`实例,然后通过...
这个过程中,如果其他线程也尝试添加元素,可能会遇到以下问题: 1. 数据丢失:在复制过程中,其他线程的添加操作可能会被“错过”,导致某些元素未被添加到列表。 2. 指针冲突:如果两个线程同时尝试扩容,可能会...
wait()会阻塞当前线程,直到指定的线程结束。 总的来说,Qt的线程和多线程功能强大且灵活,适用于各种并发编程需求。通过深入理解和熟练运用这些工具,开发者能够编写出高效、稳定且用户友好地多线程应用程序。在...
当所有非守护线程结束时,即使还有守护线程在运行,JVM也会退出。我们可以使用`setDaemon(true)`方法将线程设置为守护线程。 6. 线程优先级: Java线程有10个优先级(MIN_PRIORITY, NORM_PRIORITY, MAX_PRIORITY)...
本篇文章将深入探讨如何在MFC中创建多线程,特别是工作者线程,并且会针对`AfxBeginThread`和`BeginThread`两种方法进行比较。 首先,我们来看标题所提到的“MFC创建多线程(工作者线程)demo”。工作者线程通常...
- 信号和槽:为了与主线程或其他线程通信,`WorkThread`可能会发出一些信号,当任务完成或者有进度更新时,其他对象可以通过连接这些信号来接收通知。 **5. 简单实例** 一个典型的使用`WorkThread`的例子可能是这样...
4. **在工作线程中更新进度**:工作线程执行任务时,会周期性地更新进度。为了在UI线程中安全地更新控件,我们需要使用消息机制,如发送自定义消息到主线程。可以使用`PostMessage()`或`SendMessage()`函数,但前者...
当一个线程进入`lock`块后,其他试图进入的线程将会被阻塞,直到持有锁的线程退出。 在实际的多线程应用中,除了`lock`,还可以使用`Monitor`、`Mutex`、`Semaphore`等其他同步机制来实现互斥和资源限制。例如,`...
合理分配线程优先级可以优化程序性能,但过度依赖优先级可能会导致优先级反转或死锁。 4. **线程通信**:线程间通信是多线程编程中的重要环节,可以通过消息队列、共享内存或信号量等方式实现。在LabWindows CVI中...
- **线程安全**:多线程环境下,多个线程可能会访问同一资源,因此需要确保数据的正确性和一致性,避免竞态条件和死锁。 - **线程优先级**:可以通过设置线程优先级来调整线程的执行顺序,但过度依赖优先级可能导致...
在多线程环境中,线程间的同步和通信也涉及线程状态的判断。例如,`TThread.Synchronize`和`TThread.Queue`方法可以确保在主线程中安全地执行代码。`TThread.OnTerminate`事件可用于在线程结束时执行清理工作。 5....
总之,C#的线程编程提供了丰富的功能,但同时也伴随着复杂性。正确地使用单线程、多线程和线程管理技术,可以显著提升程序的性能和用户体验。通过学习和实践,你可以更好地驾驭C#的并发世界,编写出高效且稳定的软件...
在这个例子中,`get()`方法用于等待并获取异步计算的结果,同时也等待对应的线程结束。 总的来说,C++提供多种方式来管理线程的生命周期,包括`join()`、`detach()`以及`std::future`和`std::async`。理解这些工具...
1. `corePoolSize`: 核心线程数,即使无任务执行,也会保留这些线程。 2. `maximumPoolSize`: 最大线程数,当任务队列满时,线程池会创建新的线程执行任务,直到达到这个上限。 3. `keepAliveTime`: 当线程数超过...