Java多线程编程
由于可视化和分析大量线程可以从工具中受益,jcmd 除了纯文本外,还可以以 JSON 格式发出新的线程转储:
$ jcmd <pid> Thread.dump_to_file -format=json <file>
$ jcmd <pid> Thread.dump_to_file -format=json <file>
Java多线程编程_zhaoliwen是猪啊的博客-CSDN博客
Java多线程(一)实现多线程
在Java中,可以用Thread、Runnable以及Callable实现多线程
Thread 实现多线程
用Thread方法那么就是目标类继承(extends)Thread类,然后重写父类的run函数,在执行多线程程序时,使用start函数执行。
class sellTicket extends Thread{
private int tickets = 20;
@Override
public void run() {
try {
this.sell();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void sell() throws InterruptedException {
while(tickets>0)
{
System.out.println("卖了一张票,现在还有"+--this.tickets);
Thread.sleep(100);
}
}
}
public class testThread {
public static void main(String[] args) throws InterruptedException {
sellTicket st = new sellTicket();
st.start();
int index = 0;
while(true) {
System.out.println("--------------");
Thread.sleep(100);
if(index++>30)
break;
}
}
}
如果不使用多线程,那么看main函数的话,肯定是先卖票(输出卖票信息),再输出----------,但是使用了多线程以后,就是主线程main函数以及sellTicket 线程一起运行,得到了如下的结果。
Runnable 实现多线程
用Runnale实现多线程的方法与Thread是类似的,不同的是这个是implements Runnale,在执行多线程时是new一个Thread对象,并将Runnale的对象放入Thread对象中,再进行start()。
class sellTicket implements Runnable{
private int tickets = 20;
@Override
public void run() {
try {
this.sell();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void sell() throws InterruptedException {
while(tickets>0)
{
System.out.println("卖了一张票,现在还有"+--this.tickets);
Thread.sleep(100);
}
}
}
public class testThread {
public static void main(String[] args) throws InterruptedException {
sellTicket st = new sellTicket();
new Thread(st).start();
int index = 0;
while(true) {
System.out.println("--------------");
Thread.sleep(100);
if(index++>30)
break;
}
}
}
结果与上一个方法相同
Callable实现多线程
Callable实现多线程和上面两种的区别在于Callable多线程操作后可以有返回值,其次,用Callable实现的类的多线程操作写在call()函数中,具体可以看下面代码:
class TestCall implements Callable<String>
{
@Override
public String call() throws Exception {
for (int i=0;i<10;i++)
{
System.out.println(Thread.currentThread().getName()+" "+i);
}
return Thread.currentThread().getName() + "完成线程操作";
}
}
public class testThread {
public static void main(String[] args) throws InterruptedException, ExecutionException {
TestCall t1 = new TestCall();
TestCall t2 = new TestCall();
TestCall t3 = new TestCall();
//创建执行服务
ExecutorService service = Executors.newFixedThreadPool(3);
//提交执行
Future<String> r1 = service.submit(t1);
Future<String> r2 = service.submit(t2);
Future<String> r3 = service.submit(t3);
//获取结果
String rs1 = r1.get();
System.out.println(rs1);
String rs2 = r2.get();
System.out.println(rs2);
String rs3 = r3.get();
System.out.println(rs3);
//关闭服务
service.shutdownNow();
}
}
结果如下图所示
Callable不能和Runnable一样直接放入Thread类执行start方法,它可以通过FutureTask来做中间媒介。
public class ConcurrentTools {
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread thread = new MyThread();
FutureTask futureTask = new FutureTask(thread);
new Thread(futureTask,"A").start();
new Thread(futureTask,"B").start();//结果会被缓存,只打印一次
Integer i = (Integer) futureTask.get();//get会产生阻塞,最好放到最后执行
System.out.println(i);
}
}
class MyThread implements Callable<Integer>
{
@Override
public Integer call() throws Exception {
System.out.println("call");
return 123;
}
}
Thread 与 Runnable 的区别和联系
- Runnable的实现方式是实现其接口
- Thread的实现方式是继承其类
- Thread实现了Runnable接口并进行了扩展,而Thread和Runnable的实质是实现的关系,不是同类东西,所以Runnable或Thread本身没有可比性。
初学者会有这样一个错觉:Runnable更容易可以实现多个线程间的资源共享,而Thread却不行,但实际上却不是这样的。
这是一段由Runnable方式写成的多线程代码
class sellTicket implements Runnable{
static int tickets = 20;
static Object o = new Object();
@Override
public void run() {
try {
this.sell();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void sell() throws InterruptedException {
while (tickets > 0) {
synchronized (o) {
if(tickets<=0)
break;
System.out.println(Thread.currentThread().getName() + "卖了一张票,现在还有" + --this.tickets);
Thread.sleep(100);
}
}
}
}
public class testThread {
public static void main(String[] args) throws InterruptedException, ExecutionException {
sellTicket st1 = new sellTicket();
sellTicket st2 = new sellTicket();
sellTicket st3 = new sellTicket();
new Thread(st1,"1").start();
new Thread(st2,"2").start();
new Thread(st3,"3").start();
}
}
然后将上段代码改成Thread方式的如下
public class testThread {
public static void main(String[] args) throws InterruptedException, ExecutionException {
sellTicket st1 = new sellTicket();
sellTicket st2 = new sellTicket();
sellTicket st3 = new sellTicket();
st1.start();
st2.start();
st3.start();
}
}
class sellTicket extends Thread{
static int tickets = 20;
static Object o = new Object();
@Override
public void run() {
try {
this.sell();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void sell() throws InterruptedException {
while (tickets > 0) {
synchronized (o) {
if(tickets<=0)
break;
System.out.println(Thread.currentThread().getName() + "卖了一张票,现在还有" + --this.tickets);
Thread.sleep(100);
}
}
}
}
由此看无论哪种方式都可以实现多个线程之间的资源共享,只需要做好同步或者锁的操作即可。