特点:
单核CPU在任意时间点都只能运行一个进程
宏观是并行,微观串行
线程:又称轻量级进程(Light Weight Process)
程序中的一个顺序控制流程,同时也是CPU的基本调度单位
进程由多个线程组成,彼此完成不同的任务,交替执行,我们叫多线程
进程和线程的区别:进程是操作系统 资源分配的基本单位,而线程是CPU的基本调度单位
一个程序运行后至少有一个进程
一个进程可以包括多个线程,但是最少需要一个线程
进程间不能共享数据段地址,但同进程的线程之间可以
线程组成CPU时间片:操作系统(OS)会为每个线程分配执行时间
运行数据
堆空间:储存线程需使用的对象,多个线程可以共享堆中的对象
栈空间:储存线程所需要的局部变量,每个线程都有独立的栈
创建线程JAVA中创建线程主要有两种方法
继承Thread类
实现Runnable接口
继承Thread类
步骤:
编写类,继承Thread
重写run方法
创建线程对象
调用start方法启动线程,(不能调用run方法)
package com.cs.test;
public class Test006 {
public static void main(String[] args) {
MyThread1 myThread1 = new MyThread1();
//启动线程
myThread1.start();
}
}
//继承Thread类
class MyThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i <20 ; i++) {
System.out.println("子线程"+i);
}
}
}
获取线程名称
getName()
Thread.currentThread().getName()
package com.cs.test;
public class Test006 {
public static void main(String[] args) {
MyThread1 myThread1 = new MyThread1();
myThread1.start();
}
}
class MyThread1 extends Thread{
@Override
public void run() {
for (int i = 0; i <20 ; i++) {
System.out.println(Thread.currentThread().getName()+"吃饭了");
}
}
}
案例:
实现四个窗口卖火车票
package com.cs.test;
public class Test006 {
public static void main(String[] args) {
MyThread1 myThread1 = new MyThread1();
MyThread1 myThread2 = new MyThread1();
MyThread1 myThread3 = new MyThread1();
MyThread1 myThread4 = new MyThread1();
myThread1.start();
myThread2.start();
myThread3.start();
myThread4.start();
}
}
class MyThread1 extends Thread{
private static int count=200;
@Override
public void run() {
while (true){
if (count<=0){
break;
}
System.out.println(Thread.currentThread().getName()+"卖了第"+count+"张票");
count--;
}
}
}
实现Runnable接口:
步骤
编写类实现Runnable接口,并实现run方法
创建Runnable类实现对象
创建线程对象,传递实现类对象
启动线程
class MyThread1 implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() +);
}
}
package com.cs.test;
public class Test006 {
public static void main(String[] args) {
//创建对象
MyThread1 myThread1 = new MyThread1();
Thread thread = new Thread(myThread1,"我的线程");
thread.start();
for(int i=0;i<50;i++) {
System.out.println("main............"+i);
}
}
}
线程状态:
新建,就绪,运行,终止
常用方法:
Thread.sleep:让线程进入休眠
Thread.yield;当前线程主动放弃时间片,回到就绪状态,竞争下一个时间片
Thread.join:允许线程到其他线程中去
Thread.setPriority(int):线程优先级为1~10,默认5.,优先级越高,获得CPU的几率越大
Thread.setDaemon(blooen):设置为守护线程有两种用户线程(前台线程),守护线程(后台线程)
线程状态(等待)
新建,就绪,运行,等待,终止
线程安全线程不安全:
当多线程并发访问临界资源时,如果破坏原子操作,可能会造成数据不一致
临界资源:共享资源,一次允许一个线程使用,才可以保证其正确性
原子操作:不可分割的多步操作,被视作一个整体,其顺序和步骤都不可以被打乱或缺缺失
public class ThreadSafe {
private static int index=0;
public static void main(String[] args) throws Exception{
//创建数组
String[] s=new String[5];
//创建两个操作
Runnable runnableA=new Runnable() {
@Override
public void run() {
//同步代码块
synchronized (s) {
s[index]="hello";
index++;
}
}
};
Runnable runnableB=new Runnable() {
@Override
public void run() {
synchronized (s) {
s[index]="world";
index++;
}
}
};
//创建两个线程对象
Thread a=new Thread(runnableA,"A");
Thread b=new Thread(runnableB,"B");
a.start();
b.start();
a.join();//加入线程
b.join();//加入线程
System.out.println(Arrays.toString(s));
}
同步代码块
语法
synchronized(临界资源对象){
//对临界资源对象加锁
//代码(原子操作)
}public class Ticket implements Runnable{
private int ticket=100;
//创建锁
//private Object obj=new Object();
@Override
public void run() {
while(true) {
synchronized (this) {//this ---当前对象
if(ticket<=0) {
break;
}
System.out.println(Thread.currentThread().getName()+"卖了第"+ticket+"票");
ticket--;
}
}
}
}
线程状态(阻塞)
新建,就绪,运行,阻塞,终止
同步方法:语法: synchronized 返回值类型 方法名称(形参列表){
//对当前对象(this)加锁 // 代码(原子操作)
}
同步规则:
只有在调用包含同步代码块的方法,或者同步方法时,才需要对象额锁标记
如调用不包含同步代码块的方法,或普通方法时,就不需要锁标记,可以直接调用
JDK中线程安全的类:
-
StringBuffer
-
Vector
-
Hashtable 以上类中的公开方法,均为synchonized修饰的同步方法。



