一,实现线程有两种方式
方式1:继承Thread类
1:定义一个类MyThread继承Thread类
2:在MyThread卖中重写run()方法
3:创建MyThread类的对象
4∶启动线程 Thread类中获取和设苴线程名称的方法
void setName(String_name):_将此线程的名称更改为等于参数name
String getName():返回此线程的名称
首先定义一个类MyThread继承Thread类
package com.ithema_01;
public class MyThread extends Thread{
public MyThread(){
}
public MyThread(String name){
super(name);
}
@Override
public void run() {
for(int x = 0; x < 100; x++){
System.out.println(getName() + ":" + x);
}
}
}
测试类
public class MyThreadDemo {
public static void main(String[] args) {
// MyThread my1 = new MyThread();
// MyThread my2 = new MyThread();
/* my1.setName("dd");
my2.setName("EE");*/
//Thread(String name)
// MyThread my1 = new MyThread("ss");
// MyThread my2 = new MyThread("gg");
//
// //void start() 导致此线程开始执行;java须立即调用此线程的run方法
// my1.start();
// my2.start();
// static Thread currentThread () 返回对当前正在执行的线程对象的引用
System.out.println(
Thread.currentThread().getName());
}
}
方式2:实现Runnable接口
1 :定义—个类MyRunnable实现Runnable接口
2:在MyRunnable类中重写run()方法
3:创建MyRunnable类的对象
4:创建Thread类的对象,把MyRunnable对象作为构造方法的参数
5:启动线程
定义—个类MyRunnable实现Runnable接口
public class MyRunnable implements Runnable {
@Override
public void run() {
for(int x = 0; x < 100; x++){
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
}
测试类
public class MyRunnableDemo {
public static void main(String[] args) {
//创建MyRunnable类的对象
MyRunnable my = new MyRunnable();
//创建Thread类的对象,把MyRunnable对象作为构造方法的参数
// Thread t1 = new Thread(my);
// Thread t2 = new Thread(my);
//Thread (Runnable target, String name)
Thread t1 = new Thread(my,"gg");
Thread t2 = new Thread(my,"qq");
//启动线程
t1.start();
t2.start();
}
}
二,线程优先级
Thread类中设置和获取线程优先级的方法
public final void setPriority(int newPriority):更改此线程的优先级
public final int getPriority():返回此线程的优先级
定义TreadPriority类
public class TreadPriority extends Thread{
public TreadPriority(String name) {
super(name);
}
@Override
public void run() {
for(int x = 0; x < 100; x++){
System.out.println(getName() + ":" + x);
}
}
}
定义测试类
public class TreadPriorityDemo {
public static void main(String[] args) {
TreadPriority tp1 = new TreadPriority("dd");
TreadPriority tp2 = new TreadPriority("ff");
TreadPriority tp3 = new TreadPriority("gg");
// public final void setPriority(int newPriority):更改此线程的优先级
/* System.out.println(tp1.getPriority());//5
System.out.println(tp2.getPriority());//5
System.out.println(tp3.getPriority());//5
*/
//public final void setPriority(int newPriority):更改此线程的优先级
/* System.out.println(Thread.MAX_PRIORITY);//10
System.out.println(Thread.MIN_PRIORITY);//1
System.out.println(Thread.NORM_PRIORITY);//5*/
//设置正确的优先级
tp1.setPriority(1);
tp2.setPriority(10);
tp3.setPriority(1);
tp1.start();
tp2.start();
tp3.start();
}
}
三,线程控制
1,void setDaemon (boolean on):将此线程标记为守护线程,当运行的线程都是守护线程时,Javo虚拟机将退出
继承类:
public class ThreadDaemon extends Thread {
public ThreadDaemon(String name) {
super(name);
}
@Override
public void run() {
for(int x = 0; x < 100; x++){
System.out.println(getName() + ":" + x);
}
}
}
测试类:
public class ThreadDaemonDemo {
public static void main(String[] args) {
ThreadDaemon td1 = new ThreadDaemon("张飞");
ThreadDaemon td2 = new ThreadDaemon("关羽");
//设置主线程为刘备
Thread.currentThread().setName("刘备");
//设置守护线程
td1.setDaemon(true);
td2.setDaemon(true);
td1.start();
td2.start();
for(int x = 0; x < 10; x++){
System.out.println(Thread.currentThread().getName() + ":" + x);
}
}
2,void join():等待这个线程死亡
继承类:
public class ThreadJoin extends Thread {
public ThreadJoin(String name) {
super(name);
}
@Override
public void run() {
for(int x = 0; x < 100; x++){
System.out.println(getName() + ":" + x);
}
}
}
测试类:
public class ThreadJoinDemo {
public static void main(String[] args) throws InterruptedException {
ThreadJoin tj1 = new ThreadJoin("康熙");
ThreadJoin tj2 = new ThreadJoin("老四");
ThreadJoin tj3 = new ThreadJoin("老八");
tj1.start();
tj1.join();
tj2.start();
tj3.start();
}
}
3,static void sleep(Long willis)。使当前正在执行的线程停留〈暂停执行)指定的亳秒数
继承类:
public class ThreadSleep extends Thread {
public ThreadSleep(String name) {
super(name);
}
@Override
public void run() {
for(int x = 0; x < 100; x++){
System.out.println(getName() + ":" + x);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
实现类:
public class ThreadSleepDemo {
public static void main(String[] args) {
ThreadSleep ts1 = new ThreadSleep("曹操");
ThreadSleep ts2 = new ThreadSleep("孙权");
ThreadSleep ts3 = new ThreadSleep("刘备");
ts1.start();
ts2.start();
ts3.start();
}
}
四,线程安全类
StringBuffe , Vector ,Hashtable
public class ThreadDemo {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
StringBuilder sb2 = new StringBuilder();
Vector<String> v = new Vector<String>();
ArrayList<String> array = new ArrayList<String>();
Hashtable<String,String> ht = new Hashtable<String, String>();
HashMap<String,String> hm = new HashMap<String, String>();
//static <T> list<T> synchronizedList(List<T> list)返回有指定列表支持的同步(线程安全)列表
List<String> list = Collections.synchronizedList(new ArrayList<String>());//将线程不安全集合转为线程安全集合
}
}
五,案例
需求:
某电影院目前正在上映国产大片,共有10o张票,而它有3个窗口卖票,请设计一个程序模拟该电影3院卖票
思路:
1:定义一个类sellTicket实现Runnable接口,里面定义一个成员变量: private int tickets = 100;
2:在seLLTicket类中重写run()方法实现卖票,代码步骤如下
A:判断票数大于e,就卖票,并告知是哪个商口卖的
B:卖了票之后,总票救要诚1
C:票没有了,也可能有人来间,所以这里用死循环让卖票的动作一直执行
3:定义—个测试类selLTicketDemo,里面有main方法,代码步彩如下
A:创建sellTicket类的对象
B:创建三个Thread类的对象,把sellTicket对象作为构造方法的参数,并给出对应的窗口名称
c:启动线程
继承类:
public class SellTicket implements Runnable {
private int tickets = 100;
private Lock lock = new ReentrantLock();
@Override
public void run() {
while (true) {
try {
lock.lock();
if (tickets > 0) {
//使当前正在执行的线程停留
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在售卖" + tickets + "张票");
tickets--;
}
}finally {
lock.unlock();
}
}
}
}
测试类:
public class SellTicketDemo {
public static void main(String[] args) {
//创建sellTicket类的对象
SellTicket st = new SellTicket();
//创建三个Thread类的对象,把sellTicket对象作为构造方法的参数,并给出对应的窗口名称
Thread t1 = new Thread(st,"窗口一");
Thread t2 = new Thread(st,"窗口二");
Thread t3 = new Thread(st,"窗口三");
//启动线程
t1.start();
t2.start();
t3.start();
}
}
六,生产者消费者问题
方法:
案例讲解:买牛奶
生产者消费者案例中包含的类,
1:奶箱类(Box):定义一个成员变量,表示第x瓶奶,提供存储牛奶和获取牛奶的操作
2:生产者类(Producer):实现Runnable接口,重写run()方法,调用存储牛奶的操作
3:消费者类(Customer)。实现Runnable接口,重写run()方法,调用获取牛奶的操作
4:测试类(BoDemo):里面有main方法,main方法中的代码步骤如下
A:创建奶箱对象,这是共亨数据区域
B:创建生产者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作
c:创建消费者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用获取牛奶的操作
D:创建2个线程对象,分别把生产者对象和消费者对象作为构造方法参数传递
E:启动线程
Box类:
public class Box {
//定义一个成员变量,表示第x瓶奶
private int milk;
//定义一个成员变量,表示奶箱状态
private boolean state = false;
//提供存储牛奶和获取牛奶的操作
public synchronized void put(int milk){
//如果有牛奶就等待消费
if (state){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//如果没有牛奶,就生产牛奶
this.milk = milk;
System.out.println("送奶工将第" + this.milk + "瓶奶放入奶箱");
//生产完毕之后。修改奶箱状态
state = true;
//唤醒其他的等待线程
notifyAll();
}
public synchronized void get(){
//如果没有牛奶就等待生产
if(!state){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//有牛奶就拿
System.out.println("生产者拿第" + this.milk + "瓶奶");
//拿了之后。修改奶箱状态
state = false;
//唤醒其他的等待线程
notifyAll();
}
}
Producer类:
public class Producer implements Runnable {
private Box b;
public Producer(Box b){
this.b = b;
}
@Override
public void run() {
for(int x = 1; x <= 5; x++){
b.put(x);
}
}
}
Customer类:
public class Customer implements Runnable {
private Box b;
public Customer(Box b){
this.b = b;
}
@Override
public void run() {
while (true){
b.get();
}
}
}
测试类:
public class BoxDemo {
public static void main(String[] args) {
//创建奶箱对象,这是共亨数据区域
Box b = new Box();
//创建生产者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作
Producer p = new Producer(b);
//:创建消费者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用获取牛奶的操作
Customer c = new Customer(b);
//创建2个线程对象,分别把生产者对象和消费者对象作为构造方法参数传递
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
//启动线程
t1.start();
t2.start();
}
}
七,问题解决
1,同步代码块解决数据安全问题
同步代码块
锁多条语句操作共享数据,可以使用同步代码块实现
格式:
synchronized(任意对象){
多条语句操作共享数据的代码
}
synchronized(任意对象):就相当于给代码加锁了,任意对象就可以看成是一把锁
解决安全问题环境
同步方法:
就是把synchronized关键字加到方法上
格式:
修饰符 synchronized 返回值类型 方法名(方法参数){}
同步方法的锁对象是什么呢?
this
同步静态方法:就是把synchronized关键字加到静态方法上
格式:
修饰符 static synchronized 返回值类型 方法名(方法参数{}
锁对象:类名 + .class
2.lock锁
Lock中提供了获得锁和释放锁的方法
void lock():获得锁
void unLock():释放锁
Lock是接口不能直接实例化,这里采用它的实现类ReentrantLock来实例化
ReentrantLock():创建—个ReentrantLock的实例