线程与进程
线程与进程的概念
进程∶指一个内存中运行的应用程序,每个进程都有自己独立的一块内存空间,一个进程中可以启动多个线程。比
如在Windows系统中,一个运行的exe就是一个进程。
线程∶指进程中的一个执行流程,一个进程中可以运行多个线程。比如java.exe进程中可以运行很多线程。线程总
是属于某个进程,进程中的多个线程共享进程的内存。进程中被启动的第一个线程被称为主线程,随后启动的线程
都是子线程。
线程的实现
线程实现方式(一) 编码简单
创建线程类
- 创建类继承Thread类
- 重写run()方澳
启动线程
-
执行线程类对象的实例方法start()启动线程
-
启动线程后,会运行线程类中的run()方法,该方法会运行在子线程中
package cn.iceson;
/**
* 1.自定义一个类继承Thread
* 2.重写run方法,并且在run方法中添加线程执行的操作
* 3.创建自定义类对象
* 4.通过这个对象调用start()方法启动线程(start()方法是从Thread类中继承下来的,用于启动线程)
*/
public class MyThread extends Thread{
//线程执行的方法
@Override
public void run() {
for(int i=0;i<10;i++){
System.out.println("i="+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package cn.iceson;
public class Test {
public static void main(String[] args) {
MyThread myThread=new MyThread();
myThread.start();//启动线程,执行run方法
}
}
线程实现方式(二)扩展性强
创建线程类
-
创建类实现Runnable接口
-
实现run()方法
启动线程
- 创建自定义类对象
- 创建Thread对象(将自定义类对象作为参数传入)
- 调用Thread对象的实例方法start)
package cn.iceson;
/**
* 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) {
e.printStackTrace();
}
}
}
}
package cn.iceson;
public class Test {
public static void main(String[] args) {
MyThread myThread=new MyThread();
Thread thread=new Thread(myThread);
thread.start();
}
}
两种创建线程方式的比较
使用继承Thread的方法创建
- 优点:编码简单
- 缺点︰扩展性较差,如果一个类继承了Thread类,那么他就无法再继承其他类了。
使用实现Runnable接口的方式创建
- 优点︰不论你的类是否有继承其他类或者实现其他接口,都可以实现Runnable接口。扩展性较好。
- 缺点︰代码稍微复杂
线程睡眠
线程休眠
- Thread.sleep()静态方法强制当前正在执行的线程休眠(暂停执行),以“减慢线程”。
- 线程睡眠的原因∶线程执行太快,或者需要强制进入下一轮。释放CPU资源,让其他线程有更多的机会执行。
线程同步
线程同步的必要性
- 当多个线程操作同一个变量时,造成该变量的未知性。(以计数为例)
- 可见,当多个线程操作同一变量时,很有可能出现“打架”的情况,那么如何让他们有秩序的运行呢﹖(当有一个线程正在使用该变量的时候,其他线程都必须等待)
- 线程同步就是为了解决这类问题而出现的。
线程同步synchronized
- 使用synchronized关键字可以实现线程间的同步。
synchronized可以同步
- 实例方法
- 类方法
- 代码块
同步实例方法
- 使用synchronized修饰实例方法
语法
- synchronized)<返回类型><函数名>)
- 使用synchronized修饰实例方法的效果
一同一个对象的该实例方法,在同一时刻只能被一个线程执行(举例计数)。
-比如︰线程A正在执行对象a的该实例方法,此时线程B如果也要运行对象a的该实例方法就必须等待,但是,如果线程B是要运行对象b的该实例方法,任然可以执行。
package cn.iceson2;
public class MyThread extends Thread{
private String name;
private Entry entry;
//构造器:初始化成员变量
public MyThread(Entry entry,String name) {
this.name=name;
this.entry=entry;
}
@Override
public void run() {//线程执行的方法
//通过对象调用方法
entry.show(name);
}
}
class Entry{
//线程同步实例方法:只对同一个对象调用此方法生效,如果使用不同的对象,那么同步失效
//实例方法
public synchronized void show(String name){//变量表示线程名称
for(int i=0;i<10;i++){
System.out.println(name+"----"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package cn.iceson2;
public class Test {
public static void main(String[] args) {
Entry entry=new Entry();
MyThread mt1=new MyThread(entry, "线程1");
mt1.start();
MyThread mt2=new MyThread(entry, "线程2");
mt2.start();
}
}
同步类方法
-
同步类方法
使用synchronized修饰类方法
-
语法
static synchronized<返回类型><函数名>()
-
使用synchronized修饰类方法的效果
该类方法,在同一时刻只能被一个线程执行(举例计数))。
//线程同步类方法:在多个线程中无论使用同一个对象还是不同对象来调用此方法,同步都生效
//类方法
public synchronized static void show(String name){//变量表示线程名称
for(int i=0;i<10;i++){
System.out.println(name+"----"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
同步代码块
-
同步代码块
可以让一个方法中部分代码被同步,多个线程不能同时访问代码块,会阻塞等待。
synchronized (Object的对象){代码块}
使用同一个对象访问该代码块时,同步才生效
//使用同一个对象访问该代码块时,同步才生效
// 同步代码块
public void show(String name) {// 变量表示线程名称
synchronized (this) {//同步代码块
for (int i = 0; i < 10; i++) {
System.out.println(name + "----" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}