1.线程的启动方式
开启主要有两种:继承Thread和实现cannable接口;
- 继承Thread:
public class Practice {
public static void main(String[] args) {
// 继承 Thread 任务:copy文件
Copy c = new Copy();
c.start();
}
}
class Copy extends Thread{
@Override
public void run() {
File filename = new File("a.txt");
File copyname = new File("copy.txt");
try {
copyFile(filename,copyname );
System.out.println("复制成功");
} catch (Exception e) {
e.printStackTrace();
}
}
private void copyFile(File fileName,File copyName) throws Exception {
FileInputStream fis = new FileInputStream(fileName);
FileOutputStream fos = new FileOutputStream(copyName);
int len = 0;
byte[] byt= new byte[1024];
while ((len=fis.read(byt))!=-1) {
fos.write(byt, 0, len);
fos.flush();
}
fis.close();
fos.close();
}
}
- 实现cannable接口:
public class Practice {
public static void main(String[] args) {
// 实现runnable 任务:输出任意范围字母
Print p= new Print();
Thread thread = new Thread(p);
thread.start();
}
}
class Print implements Runnable{
@Override
public void run() {
int a = (int) (Math.random()*26+97);
int b = (int) (Math.random()*26+97);
if (a>=b) {
for (int i = b; i <= a; i++) {
System.out.print("实现Runable"+(char)i+" ");
}
}else if (a<b) {
for (int i = a; i <= b; i++) {
System.out.print("实现Runable"+(char)i+" ");
}
}
}
}
2.线程的生命周期
3.线程池
- 线程池的开启:
Executors 工厂类来产生线程池。
构造方法
public static ExecutorService newCachedThreadPool()
public static ExecutorService newFixedThreadPool(int nThreads)
public static ExecutorService newSingleThreadExecutor()
*/
public class ThreadDemo01 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 创建线程池
ExecutorService pool = Executors.newFixedThreadPool(3);
// 将线程放入到池中
pool.submit(new MyRunnable());
Future<Integer> future = pool.submit(new MyCallable());
pool.submit(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "线程池匿名内部类实现Runnable方式开启线程:" + i);
}
}
});
System.out.println("1~100的和为:" + future.get());
// 结束线程池
pool.shutdown();
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + "线程池实现Runnable方式开启线程:" + i);
}
}
}
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum = 0;
for (int i = 1; i <= 100; i++) {
System.out.println(Thread.currentThread().getName() + "线程池实现Callable方式开启线程:" + i);
sum += i;
}
return sum;
}
}
4.线程同步
- 见上篇博客:线程同步案例浅析
5.线程通信:
- 通过构造方法 A -> B A在启动之前传递给B
- 通过实现Callable接口的方式 A -> B B在执行结束之后将数据回传给A
- 利用接口回调方式传递数据
- 利用同步锁串行实现数据传递
- 利用等待唤醒机制
下面主要解释下后三种方法:
(1.)接口回调
1.创建一个回调接口[电话号码],接口中书写方法 A->B
方法的形参就是 B线程使用形参传递给A线程
方法的返回值就是 A线程使用返回值传递给B线程
2.A线程将这个回调接口通过构造方法传递给B线程
3.B线程在使用这个接口,即接口回调
public class Test {
public static void main(String[] args) {
BThread thread = new BThread("B", new ICallBack() {
@Override
public String fun(int a, int b, String message) {
int sum = a + b;
System.out.println("收到了来自于B线程的消息: " + message);
return sum + ":" + BThread.currentThread().getName();
}
});
thread.start();
}
}
class AThread extends Thread {
@Override
public void run() {
}
}
class BThread extends Thread {
private ICallBack cb;
public BThread() {}
public BThread(String name, ICallBack cb) {
super(name);
this.cb = cb;
}
public void setCb(ICallBack cb) {
this.cb = cb;
}
public void run() {
String result = cb.fun(10, 20, "我是线程B带过来两个整数数据");
System.out.println("收到了来自于A线程的数据: " + result);
}
}
// 回调接口
interface ICallBack {
String fun(int a, int b, String message);
}
(2.)利用同步锁串行实现数据传递
public class Test9 {
public static void main(String[] args) {
MyObject object =new MyObject();
// 三个线程共享一个锁对象
MythreadA ma = new MythreadA(object);
MythreadB mb = new MythreadB(object);
MythreadC mc = new MythreadC(object);
ma.start();
mb.start();
mc.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(object.getCount());
}
}
class MythreadA extends Thread {
private MyObject object;
public void run() {
object.methodA("A");
System.out.println("ma执行完后count为"+object.getCount());
};
public MythreadA() {
}
public MythreadA(MyObject object) {
this.object = object;
}
public Object getObject() {
return object;
}
public void setObject(MyObject object) {
this.object = object;
}
}
class MythreadB extends Thread {
private MyObject object;
public void run() {
object.methodB("B");
System.out.println("mb执行完后count为"+object.getCount());
};
public MythreadB() {
}
public MythreadB(MyObject object) {
this.object = object;
}
public Object getObject() {
return object;
}
public void setObject(MyObject object) {
this.object = object;
}
}
class MythreadC extends Thread {
private MyObject object;
public void run() {
object.methodC("C");
System.out.println("mc执行完后count为"+object.getCount());
};
public MythreadC() {
}
public MythreadC(MyObject object) {
this.object = object;
}
public Object getObject() {
return object;
}
public void setObject(MyObject object) {
this.object = object;
}
}
//自定义锁对象
class MyObject {
private String count = "";
public MyObject() {
}
//同步方法的锁对象是this(为调用者),由于调用的对象为同一对象object,因此锁对象一样。
public synchronized void methodA(String message) {
System.out.println(message);
count += message;
}
public synchronized void methodB(String message) {
System.out.println(message);
count += message;
}
public synchronized void methodC(String message) {
System.out.println(message);
count += message;
}
public MyObject(String count) {
this.count = count;
}
public String getCount() {
return count;
}
public void setCount(String count) {
this.count = count;
}
@Override
public String toString() {
return "Object [count=" + count + "]";
}
}
(3.)利用等待唤醒机制
wait(),notify(),notifyll()
生产者消费者模型:
//共享资源
public class Toy {
private String name; // 玩具名称
private int num; // 玩具数量
private boolean flag; // 是否有玩具, 有表示true,没有表示false
public Toy() {
super();
}
public Toy(String name, int num, boolean flag) {
super();
this.name = name;
this.num = num;
this.flag = flag;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
@Override
public String toString() {
return "Toy [name=" + name + ", num=" + num + ", flag=" + flag + "]";
}
}
//消费者线程
public class GetThread extends Thread {
private Toy t;
public GetThread() {
}
public GetThread(Toy t) {
this.setT(t);
}
@Override
public void run() {
while (true) {
synchronized (t) {
// 先判断是否有玩具
if (!t.isFlag()) {
// 没有,就等待生产者生产
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 有,就消费
String toyName = t.getName();
int toyNum = t.getNum();
System.out.println(toyName + "|" + toyNum);
// 消费一次数量减一
t.setNum(--toyNum);
// 消费完毕之后,就通知生产者生产
if (toyNum <= 0) {
// 设置标志位,说明没有玩具了
t.setFlag(false);
// 消费完毕之后,就通知生产者生产
t.notify();
}
}
}
}
public Toy getT() {
return t;
}
public void setT(Toy t) {
this.t = t;
}
}
//生产者线程
public class SetThread extends Thread {
private Toy t;
private int i;
public SetThread() {
super();
}
public SetThread(Toy t) {
super();
this.t = t;
}
@Override
public void run() {
while (true) {
synchronized (t) {
// 先判断是否有玩具
if (t.isFlag()) {
// 就等待消费者消费
try {
t.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
// 没有,就生产
if (i % 2 == 0) {
t.setName("Hello Kitty");
t.setNum(10);
} else {
t.setName("King");
t.setNum(5);
}
i++;
// 设置标志位,表示目前已经有数据了
t.setFlag(true);
// 生产完毕之后通知消费者消费 nofity
t.notify();
}
}
}
public Toy getT() {
return t;
}
public void setT(Toy t) {
this.t = t;
}
}
//主线程
public class ThreadDemo01 {
public static void main(String[] args) {
Toy t = new Toy();
SetThread st = new SetThread(t);
GetThread gt = new GetThread(t);
st.start();
gt.start();
}
}