并发编程(01)--多线程基础

1.关于多线程

1.1 线程与进程的区别

进程:系统中每一个正在运行的程序都是一个进程,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元

线程:是一组指令的集合,控制着进程的执行,一个进程中至少有一个线程

1.2 为什么用多线程

使用多线程可以将执行时间长的程序中的任务放到后台去处理,在一些需要等待的任务上如文件读写、网络分发数据等,使用多线程就可以更好的利用CPU的资源,从而提高程序运行的效率

2. 线程的状态

线程有5种状态:新建、就绪、运行、阻塞、死亡,如下图所示:

新建状态:当new一个线程时, 例如new Thread(r),线程还没有开始运行,此时线程处在新建状态。 当一个线程处于新生状态时,程序还没有开始运行线程中的代码

就绪状态:一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的start()方法。当线程对象调用start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行run()方法。当start()方法返回后,线程就处于就绪状态。处于就绪状态的线程并不一定立即运行run()方法,线程还必须同其他线程竞争CPU时间,只有获得CPU时间才可以运行线程。因为在单CPU的计算机系统中,不可能同时运行多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。对多个处于就绪状态的线程是由java运行时系统的线程调度程序(thread scheduler)来调度的。

运行状态:当线程竞争到CPU时间之后,执行run()方法,进入运行状态

阻塞状态:线程运行过程中,可能由于各种原因进入阻塞状态:

1)线程通过调用sleep方法进入睡眠状态;

2)线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;

3)线程试图得到一个锁,而该锁正被其他线程持有;

4)线程在等待某个触发条件;

所谓阻塞状态是正在运行的线程没有运行结束,暂时让出CPU,这时其他处于就绪状态的线程就可以获得CPU时间,进入运行状态。

死亡状态:有两种原因会导致线程进入死亡状态:

1)run()方法执行完成正常死亡

2)发生异常终止了run()方法而进入死亡状态

3. 创建线程的方法

3.1 继承Thread类,重写run()方法

class CreateThread extends Thread {

	publicvoid run() {
		// run方法中编写 多线程需要执行的代码
	}
}

3.2 实现Runnable接口,重写run()方法

class CreateRunnable implements Runnable {

	@Override
	publicvoid run() {
		//run方法中编写多线程需要执行的代码
	}

}

3.3 匿名内部类方式

Thread thread = new Thread(new Runnable() {
			public void run() {
				//run方法中编写多线程需要执行的代码
			}
});

4. 常用的方法

4.1 join()

join():当线程B执行到了线程A的.join()方法时,B线程就会等待,等A线程都执行完毕,B线程才会执行,join可以用来临时加入线程执行。

public class Thread002 {

	public static void main(String[] args) {
		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				for (int i = 0; i < 10; i++) {
					System.out.print("这个是t1线程:" + i +"\t");
				}
				System.out.println("\n--------------分割线------------------");
			}
		});

		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					t1.join();

				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				for (int i = 0; i < 10; i++) {
					System.out.print("这个是t2线程:" + i+ "\t");
				}
				System.out.println("\n--------------分割线------------------");
			}
		});

		Thread t3 = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					t2.join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				for (int i = 0; i < 10; i++) {
					System.out.print("这个是t3线程:" + i +"\t");
				}

			}
		});
		t1.start();
		t2.start();
		t3.start();

	}

}

4.2 sleep()、yield()

sleep():让正在执行的线程休眠,因为使用sleep方法之后,线程是进入阻塞状态的,只有当睡眠的时间结束,才会重新进入到就绪状态,而就绪状态进入到运行状态,是由系统控制的,我们不可能精准的去干涉它,所以如果调用Thread.sleep(1000)使得线程睡眠1秒,可能结果会大于1秒

public class SynTest {
    public static void main(String[] args) {
        new Thread(new CountDown(),"倒计时").start();
    }
}

class CountDown implements Runnable{
    int time = 10;
    public void run() {
        while (true) {
            if(time>=0){
                System.out.println(Thread.currentThread().getName() + ":" + time--);
                try {
                    Thread.sleep(1000);                                                    //睡眠时间为1秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

yield():和sleep方法类似,也是Thread类提供的一个静态方法,可以让正在执行的线程暂停,但是不会进入阻塞状态,而是直接进入就绪状态。相当于只是将当前线程暂停一下,然后重新进入就绪的线程池中,让线程调度器重新调度一次。也会出现某个线程调用yield方法后暂停,但之后调度器又将其调度出来重新进入到运行状态

public class SynTest {
    public static void main(String[] args) {
        yieldDemo ms = new yieldDemo();
        Thread t1 = new Thread(ms,"张三吃完还剩");
        Thread t2 = new Thread(ms,"李四吃完还剩");
        Thread t3 = new Thread(ms,"王五吃完还剩");
        t1.start();
        t2.start();
        t3.start();
    }
}
class yieldDemo implements Runnable{
    int count = 20;
    public void run() {
        while (true) {
                if(count>0){
                    System.out.println(Thread.currentThread().getName() + count-- + "个瓜");
                    if(count % 2 == 0){
                        Thread.yield();                  //线程让步
                    }
            }
        }
    }
}

原文地址:https://www.cnblogs.com/Cryptonym/p/10668764.html

时间: 2024-08-01 03:14:52

并发编程(01)--多线程基础的相关文章

python并发编程之多线程基础知识点

1.线程理论知识 概念:指的是一条流水线的工作过程的总称,是一个抽象的概念,是CPU基本执行单位. 进程和线程之间的区别: 1. 进程仅仅是一个资源单位,其中包含程序运行所需的资源,而线程就相当于车间的流水线,负责执行具代码. 2. 每个进程至少包含一个线程,由操作系统自动创建,称之为主线程 3. 每个进程可以有任意数量的线程 4.创建进程的开销要比创建进程小得多 5. 同一进程的线程间数据是共享的 6.线程之间是平等的,没有子父级关系,同一进程下的各线程的PID相同 7. 创建线程的代码可以写

并发编程之多线程基础篇及面试

线程与进程区别 每个正在系统上运行的程序都是一个进程.每个进程包含一到多个线程.线程是一组指令的集合,或者是程序的特殊段,它可以在程序里独立执行.也可以把它理解为代码运行的上下文.所以线程基本上是轻量级的进程,它负责在单个程序里执行多任务.通常由操作系统负责多个线程的调度和执行. 使用线程可以把占据时间长的程序中的任务放到后台去处理,程序的运行速度可能加快,在一些等待的任务实现上如用户输入.文件读写和网络收发数据等,线程就比较有用了.在这种情况下可以释放一些珍贵的资源如内存占用等等. 如果有大量

并发编程之多线程基础-Thread和Runnable的区别及联系(二)

上篇文章讲述了创建线程的常用方式 本篇主要分析一下Thread和Runnable两种方式创建线程的区别及联系 联系: ?Thread类实现了Runable接口. ?都需要重写里面Run方法. 区别: ?Thread方式不支持多继承,Runnable方式支持多个实现 ?Runnable更容易实现资源共享,能多个线程同时处理一个资源. 疑惑分享: 本人在理解他们区别的时候 考虑到Thread类本身就是Runnable的实现类 所以产生了一个疑惑:- 为什么Runnable可以实现共享而Thread却

day10-python并发编程之多线程协程及MySQL

第1章 python并发编程之多线程 1.1 死锁现象与递归锁 1.1.1 死锁概念 进程也有死锁与递归锁,在进程那里忘记说了,放到这里一切说了额 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程,如下就是死锁 1.1.2 博客实例 from threading import Thread,Lock import time mutexA=L

Python并发编程04/多线程

目录 Python并发编程04/多线程 1.生产消费者模型 2.线程的理论知识 2.1什么是线程 2.2线程vs进程 2.3线程的应用 3.开启进程的两种方式 3.1第一种方式 3.2第一种方式 4.线程vs进程的代码对比 4.1开启速度对比 4.2对比pid 4.3同一个进程内线程共享内部数据 5.线程的其他方法 6.join与守护线程 6.1join 6.2守护线程 7.互斥锁 Python并发编程04/多线程 1.生产消费者模型 #编程思想,模型,设计模式,理论等等,都是交给你一种编程的方

并发编程之多线程

一.并发编程之多线程 1.线程简单介绍 进程是资源单位,把所有资源集中到一起,而线程是执行单位,真正执行的是线程 每个进程都有一个地址空间,而且默认就有一个控制线程 多线程:在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间.进程之间是竞争关系,线程之间是协作关系 线程的创建开销比进程小很多,运行较快 主线程从执行层面上代表了其所在进程的执行过程 2.线程开启方式 方式一:使用替换threading模块提供的Thread from threading import Thread  d

python 学习_第四模块 并发编程(多线程)

python 学习_第四模块 并发编程(多线程) 1  开启线程方式 from threading import Thread import time def say(name): time.sleep(2) print("%s hello"%name) if __name__ =="__main__": t = Thread(target=say,args=("alex",)) t.start() print("主线程")

Java并发编程之多线程同步

线程安全就是防止某个对象或者值在多个线程中被修改而导致的数据不一致问题,因此我们就需要通过同步机制保证在同一时刻只有一个线程能够访问到该对象或数据,修改数据完毕之后,再将最新数据同步到主存中,使得其他线程都能够得到这个最新数据.下面我们就来了解Java一些基本的同步机制. Java提供了一种稍弱的同步机制即volatile变量,用来确保将变量的更新操作通知到其他线程.当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的.然而,在访问volatile变量时不会执行加锁操作

Java并发编程、多线程、线程池…

Java多线程干货系列(1):Java多线程基础http://www.importnew.com/21136.html#comment-651146 40个Java多线程问题总结http://www.importnew.com/18459.html#comment-651217 Java线程面试题 Top 50http://www.importnew.com/12773.html Java并发编程:Thread类的使用http://www.cnblogs.com/dolphin0520/p/39