Java基础---线程
这里写下关于java基础的一些知识,便于自己的复习和分享给大家共同学习! 有指教的地方请留言,共同学习进步!
一, 什么是线程?线程的基础概念
1,线程是一个程序内部的顺序控制流,可以理解为是一个程序里面不同的执行路径
2,每个分支都叫做一个线程,我们程序所写的main()叫做主分支,也叫主线程。
3,可以通过创建Thread的实例来创建新的线程
4,每个线程都是通过某个特定的Thread对象对应的run()方法来完成操作的,方法run()成为线程体,通过调用Thread类的start()方法来启动一个线程。
二,什么是进程?
进程可以看成是一个程序执行的实例,程序一旦允许就是一个进程,每个进程都拥有一个独立地址空间。
一个进程可以拥有多个线程,每个线程使用其所属的进程的栈空间。
三,线程和进程的区别?
1,每个进程都有独立的代码空间和数据,进程间的切换会有较大的开销
2,线程可以看成轻量级的进程,同一类线程共享代码和数据空间,线程切换开销较小。
3,多进程:操作系统中可以同时运行多个程序。
4,线程没有独立的内存空间
5,线程是寄生在进程中。
四,多线程:
多线程:一个进程中不只有一个线程。
为什么要使用多线程?
1,Java语言内置了多线程功能支持,简化了java多线程的编程。
2,进程之间不能共享数据,线程可以。
3,系统创建进行需要为该进程分配系统资源,创建线程代价较小
4,为了更有效的利用CPU资源,如果只有一个线程,则第二个任务必须等到第一个任务结束后才能进行。如果使用多线程,就可以在主线程执行任务时,也可以执行其他任务,不需要等待。
这里说下CPU的工作原理:
CPU 执行速度非常快,一秒钟可以算几亿次,所以CPU吧自己的时间分成了一个一个的时间片,这个时间片这个程序执行,第二个时间片另一个程序执行,以此类推。虽然有很多线程,但是一样可以在很短的时间之内把它们执行,因CPU执行的速度之快,所以我们看起来好像同一时间执行一样,其实是在一个时间点上,CPU 只有一个线程在运行。
五,启动线程和创建线程
二种主要方式:
1,继承Thread类,重写run函数,调用start()方法。
定义一个Thread的子类,继续Thread类,重写run方法, 将代码存储在run方法,让线程运行
public class ThreadDemo2 {
public static void main(String[] args) {
// 创建两个线程
ThreadDemo td1 = new ThreadDemo("zzzzzzzz");
ThreadDemo td2 = new ThreadDemo("sssss");
// 如果使用.run();也会执行,但会单线程方式执行。
td1.start();
td2.start();
// 主线程
for (int i = 0; i <6; i++) {
System.out.println("主线程" + ":run" + i);
}
}
}
// 继承Thread类
class ThreadDemo extends Thread {
// 设置线程名称
ThreadDemo(String name) {
super(name);
}
// 重写run方法。
@Override
public void run() {
for (int i = 0; i < 8; i++) {
System.out.println(this.getName() + ":run" + i);
}
}
}
2,实现Runnable接口:
定义一个类实现Runnable接口,覆盖Runnable接口中的Run方法,将要执行的代码放在run方法中,
通过Thread类创建线程对象,然后将实现Runnable接口的子类对象
public class TestRunn {
public static void main(String args[]){
Runn1 r1 = new Runn1();//这里new了一个线程类的对象出来
//r1.run();//这个称为方法调用,方法调用的执行是等run()方法执行完之后才会继续执行main()方法
Thread t = new Thread(r1);//要启动一个新的线程就必须new一个Thread对象出来
//这里使用的是Thread(Runnable target) 构造方法
t.start();//启动新的线程,新线程执行的是run()方法,新线程与主线程会一起并行执行
for(int i=0;i<10;i++){
System.out.println("maintheod:"+i);
}
}
}
/*定义一个类用来实现Runnable接口,实现Runnable接口就表示这个类是一个线程类*/
class Runn1 implements Runnable{
public void run(){
for(int i=0;i<10;i++){
System.out.println("Runn1:"+i);
}
}
}
六,Sleep/ join /yield方法
Sleep方法:
可以调用Thread的静态方法,使得当前线程休眠,单位为毫秒,由于是静态方法,可以直接用类名调用
Join方法:
线程实例的方法join()方法可以使得一个线程在另一个线程结束后再执行。如果join()方法在一个线程实例上调用,当前运行着的线程将阻塞直到这个线程实例完成了执行。
Yield方法:
让出CPU使用权 ,给其他线程执行的机会
Sleep() Demo:
public class Thread1 {
public static void main(String[] args) {
Runner1 r1 = new Runner1();
Thread t = new Thread(r1);
t.start();
for (int i = 0; i < 5; i++) {
System.out.println("main thread :"+i);
}
}
}
class Runner1 implements Runnable{
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 5; i++) {
System.out.println("Runner1 : " + i);
}
}
}
main thread:4 和Runner1:0 之间睡了5秒
Join() Demo:
public class TestThread4 {
public static void main(String args[]) {
MyThread2 thread2 = new MyThread2("mythread");
// 创建一个新线程对象,线程对象命名为mythread
thread2.start();// 启动线程
try {
thread2.join();// 调用join()方法合并线程,将子线程mythread合并到主线程里面
// 合并线程后,程序的执行的过程就相当于是方法的调用的执行过程
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i <= 5; i++) {
System.out.println("I am main Thread");
}
}
}
class MyThread2 extends Thread {
MyThread2(String s) {
super(s);
/*
* 使用super关键字调用父类的构造方法
* 父类Thread的其中一个构造方法:“public Thread(String name)”
* 通过这样的构造方法可以给新开辟的线程命名,便于管理线程
*/
}
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println("I am a\t" + getName());
// 使用父类Thread里面定义的
//public final String getName(),Returns this thread's name.
try {
sleep(1000);// 让子线程每执行一次就睡眠1秒钟
} catch (InterruptedException e) {
return;
}
}
}
}
结果如下,每隔一秒钟输出一个i am a mythread;
Yield Demo :
public class TestThread6 {
public static void main(String args[]) {
MyThread4 t1 = new MyThread4("t1");
/* 同时开辟了两条子线程t1和t2,t1和t2执行的都是run()方法 */
/* 这个程序的执行过程中总共有3个线程在并行执行,分别为子线程t1和t2以及主线程 */
MyThread4 t2 = new MyThread4("t2");
t1.start();// 启动线程t1
t2.start();// 启动线程t2
for (int i = 0; i <= 5; i++) {
System.out.println("I am main Thread");
}
}
}
class MyThread4 extends Thread {
MyThread4(String s) {
super(s);
}
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(getName() + ":" + i);
if (i % 2 == 0) {
yield();// 当执行到i能被2整除时当前执行的线程就让出来让另一个在执行run()方法的线程来优先执行
/*
* 运行时候观察到:
* 线程t1执行到(i%2==0)次时就会让出线程让t2线程来优先执行
* 而线程t2执行到(i%2==0)次时也会让出线程给t1线程优先执行
*/
}
}
}
}
运行结果为:
欢迎指教~ 后续继续。