这里写目录标题
线程与进程的概念
- 进程:指一个内存中运行的应用程序,每个进程都要自己的独立的一块内存空间,一个进程中可以启动多个线程,比如Windows系统中,一个运行的.exe就是一个进程。
- 线程:指进程中的一个执行流程,一个进程中可以运行多个线程。线程总是属于某个进程,进程中的多个线程共享进程的内存。进程中被启动的第一个线程被称为主线程,随后启动的线程都是子线程。
线程的实现
第一种方法:继承Thread类创建线程。
MyThread.java文件
package com.fs.test;
/**
* 1.自定义一个类继承Thread
* 2.重写run()方法,并且在run()方法添加线程执行的操作
* 3.创建自定义类的对象
* 4.通过这个对象调用start()方法启动线程
* 5.start()方法是Thread类中继承下来的,用于启动线程
*
*/
public class MyThread extends Thread {
@Override
public void run() {//线程执行的方法
for (int i = 1; i < 10; i++) {
System.out.println("i=" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Test.java文件
package com.fs.test;
public class Test {
public static void main(String[] args) {
MyThread mThread = new MyThread();
mThread.start();//启动线程,执行run方法
}
}
第二种方法:实现Runnable接口创建线程
MyThread.java文件
package com.fs.test;
/**
* 1.自定义一个类实现Runnable接口
* 2.重写run()方法,并在方法中添加线程执行的操作
* 3.创建自定义类的对象
* 4.创建Thread对象,并将自定义类的对象当成参数传入
* 5.通过Thread类的对象调用start()方法来启动线程
*
*/
public class MyThread implements Runnable {
@Override
public void run() {// 线程执行方法
while (true) {
System.out.println("线程执行中");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
Test.java文件
package com.fs.test;
public class Test {
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
}
}
线程的同步
线程同步的必要性
- 当多个线程操作同一变量时,可能出现“打架”的情况,那么如何让他们有秩序的运行?线程同步就是为了解决这类问题的出现。
synchronized关键字
使用synchronized关键字可以实现线程间的同步
-
synchronized可以同步
(1)实例方法
(2)类方法
(3)代码块 -
synchronized修饰实例方法
-
语法:synchronized <返回类型> <函数名>()
只对多个线程中同一个对象调用此方法时生效,如果使用的是不同对象,那么同步失效
同步实例方法
MyThread文件
package com.fs.test;
public class MyThread extends Thread {
private Entry entry;
private String name;
// 构造器:初始化成员变量
public MyThread(Entry entry, String name) {
this.entry = entry;
this.name = name;
}
@Override
public void run() {// 线程执行的方法
super.run();
// 通过对象调用方法
entry.show(name);
}
}
class Entry {
// 线程同步实例方法:只对多个线程中同一个对象调用此方法时生效,如果使用的是不同对象,那么同步失效
// 实例方法
public synchronized void show(String name) {// 变量表示线程名称
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
System.out.println(name + ":" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Test.java文件
package com.fs.test;
public class Test {
public static void main(String[] args) {
Entry entry = new Entry();
// 开启子线程1
MyThread mThread1 = new MyThread(entry, "线程1");
mThread1.start();
// 开启子线程2
MyThread mThread2 = new MyThread(entry, "线程2");//如果两个对象不同,则同步失效
mThread2.start();
}
}
结果: //当线程1抢占到资源时执行,线程2等待线程1执行完才能执行
线程1:0
线程1:1
线程1:2
线程1:3
线程1:4
线程1:5
线程1:6
线程1:7
线程1:8
线程1:9
线程2:0
线程2:1
线程2:2
线程2:3
线程2:4
线程2:5
线程2:6
线程2:7
线程2:8
线程2:9
同步类方法
- 使用synchronized修饰类方法。//静态的方法
- 语法:static synchronized <返回类型> <函数名>()
- 效果:同一时刻只能被一个线程执行。
在多个线程中无论使用同一对象还是不同对象来调用此方法,同步都生效
// 线程同步类方法:在多个线程中无论使用同一对象还是不同对象来调用此方法,同步都生效
// 类方法
public synchronized static void show(String name) {// 变量表示线程名称
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
System.out.println(name + ":" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Test文件中
package com.fs.test;
public class Test {
public static void main(String[] args) {
Entry entry = new Entry();
// 开启子线程1
MyThread mThread1 = new MyThread(entry, "线程1");
mThread1.start();
// 开启子线程2
MyThread mThread2 = new MyThread(entry, "线程2");//两个对象可以不同,同步任然生效
mThread2.start();
}
}
同步代码块
- 可以让一个方法中部分代码被同步,多个线程不能同时访问代码块,会阻塞等待。
- 语法:synchronized(Object){代码块}
- 使用同一对象访问该代码时,同步才生效。
public void show(String name) {// 变量表示线程名称
//线程同步代码块:在多个线程中使用同一个对象调用此方法的代码块时,同步才生效,使用不同对象时,同步失效
synchronized (this) {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
System.out.println(name + ":" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}